diff options
| author | Mitja Felicijan <mitja.felicijan@gmail.com> | 2023-06-27 14:50:20 +0200 |
|---|---|---|
| committer | Mitja Felicijan <mitja.felicijan@gmail.com> | 2023-06-27 14:50:20 +0200 |
| commit | 8697555125c57ae64a0c9b78514b4aac4fd523de (patch) | |
| tree | a699df53a7c35a4425f30bca86982c4341f6de40 | |
| parent | 33b2615a5038bc85036081e8b5e0da8584d88097 (diff) | |
| download | mitjafelicijan.com-8697555125c57ae64a0c9b78514b4aac4fd523de.tar.gz | |
Massive formatting and added figcaption
54 files changed, 2073 insertions, 2044 deletions
diff --git a/content/notes/cachebusting-in-hugo.md b/content/notes/cachebusting-in-hugo.md index 05ec859..707125a 100644 --- a/content/notes/cachebusting-in-hugo.md +++ b/content/notes/cachebusting-in-hugo.md | |||
| @@ -15,4 +15,3 @@ tags: [hugo] | |||
| 15 | 15 | ||
| 16 | This `6fab11c6669976d759d2992eff1dd5be` can be random string you generate use. | 16 | This `6fab11c6669976d759d2992eff1dd5be` can be random string you generate use. |
| 17 | You can use whatever you want. | 17 | You can use whatever you want. |
| 18 | |||
diff --git a/content/notes/cronjobs-github-with-actions.md b/content/notes/cronjobs-github-with-actions.md index 13e7618..4ae2f71 100644 --- a/content/notes/cronjobs-github-with-actions.md +++ b/content/notes/cronjobs-github-with-actions.md | |||
| @@ -7,17 +7,16 @@ draft: false | |||
| 7 | tags: [github] | 7 | tags: [github] |
| 8 | --- | 8 | --- |
| 9 | 9 | ||
| 10 | In the root of your repository create a folder `.github/workflows` and | 10 | In the root of your repository create a folder `.github/workflows` and in that |
| 11 | in that folder create a file a file `cron.yaml`. This file can be named | 11 | folder create a file a file `cron.yaml`. This file can be named whatever you |
| 12 | whatever you wish. But it has to be a `yaml` file. | 12 | wish. But it has to be a `yaml` file. |
| 13 | 13 | ||
| 14 | File below (`.github/workflows/cron.yaml`) describes an action that will | 14 | File below (`.github/workflows/cron.yaml`) describes an action that will trigger |
| 15 | trigger every six hours and it will curl example.com. | 15 | every six hours and it will curl example.com. |
| 16 | |||
| 17 | However. Be sure that you have enough credits. Free account is not that | ||
| 18 | generous with the minutes they give you for free. Check more about | ||
| 19 | GitHub Actions usage on their website https://docs.github.com/en/actions. | ||
| 20 | 16 | ||
| 17 | However. Be sure that you have enough credits. Free account is not that generous | ||
| 18 | with the minutes they give you for free. Check more about GitHub Actions usage | ||
| 19 | on their website https://docs.github.com/en/actions. | ||
| 21 | 20 | ||
| 22 | ```yaml | 21 | ```yaml |
| 23 | # .github/workflows/cron.yaml | 22 | # .github/workflows/cron.yaml |
diff --git a/content/notes/dcss-new-player-guide.md b/content/notes/dcss-new-player-guide.md index bbeb401..2956681 100644 --- a/content/notes/dcss-new-player-guide.md +++ b/content/notes/dcss-new-player-guide.md | |||
| @@ -7,21 +7,20 @@ draft: false | |||
| 7 | tags: [dcss] | 7 | tags: [dcss] |
| 8 | --- | 8 | --- |
| 9 | 9 | ||
| 10 | An amazing game deserves an amazing guide. All this material can be find in | 10 | An amazing game deserves an amazing guide. All this material can be find in some |
| 11 | some form on another on [craw's](https://github.com/crawl/crawl) official | 11 | form on another on [craw's](https://github.com/crawl/crawl) official repository. |
| 12 | repository. | ||
| 13 | 12 | ||
| 14 | - [DCSS Quickstart](/notes/dcss-quickstart.pdf) - Very short introduction to | 13 | - [DCSS Quickstart](/notes/dcss-quickstart.pdf) - Very short introduction to the |
| 15 | the game | 14 | game |
| 16 | - [DCSS Manual](/notes/dcss_manual.pdf) - Extensive manual about the game | 15 | - [DCSS Manual](/notes/dcss_manual.pdf) - Extensive manual about the game |
| 17 | 16 | ||
| 18 |  | 17 |  |
| 19 | 18 | ||
| 20 | **Movement and Exploration** | 19 | **Movement and Exploration** |
| 21 | 20 | ||
| 22 | - You can move around with the numpad (try numlock on and off), vi-keys, or | 21 | - You can move around with the numpad (try numlock on and off), vi-keys, or |
| 23 | clicking with the mouse. Arrow keys work, though you can't move diagonally | 22 | clicking with the mouse. Arrow keys work, though you can't move diagonally |
| 24 | with them. Pressing Shift and a direction will move until you see/hit | 23 | with them. Pressing Shift and a direction will move until you see/hit |
| 25 | something. | 24 | something. |
| 26 | - Pressing `>` will take you down a staircase, and `<` to go up a staircase. | 25 | - Pressing `>` will take you down a staircase, and `<` to go up a staircase. |
| 27 | - You can open doors by walking into them, and close them with `C`. | 26 | - You can open doors by walking into them, and close them with `C`. |
| @@ -32,33 +31,34 @@ repository. | |||
| 32 | 31 | ||
| 33 | - You can pick up items with `,` or `g`. | 32 | - You can pick up items with `,` or `g`. |
| 34 | - Wield weapons with `w`. Weapons have different stats. | 33 | - Wield weapons with `w`. Weapons have different stats. |
| 35 | - (You may also engage in Unarmed Combat, though it isn't very effective | 34 | - (You may also engage in Unarmed Combat, though it isn't very effective when |
| 36 | when untrained). | 35 | untrained). |
| 37 | - Attack monsters in melee by walking in their direction (or with Ctrl-direction). | 36 | - Attack monsters in melee by walking in their direction (or with |
| 38 | - You can wait with `.` or `s`, passing your turn - such as to get monsters | 37 | Ctrl-direction). |
| 39 | into a corridor with you. | 38 | - You can wait with `.` or `s`, passing your turn - such as to get monsters into |
| 40 | - You can rest with `5`, waiting until you are fully healed, or something | 39 | a corridor with you. |
| 40 | - You can rest with `5`, waiting until you are fully healed, or something | ||
| 41 | noteworthy happens. | 41 | noteworthy happens. |
| 42 | - Either mouseover and rightclick, or use `x` then `v` on the monster to | 42 | - Either mouseover and rightclick, or use `x` then `v` on the monster to examine |
| 43 | examine monsters. Monsters with a red border are 'dangerous' relative to | 43 | monsters. Monsters with a red border are 'dangerous' relative to your current |
| 44 | your current XP level (XL). | 44 | XP level (XL). |
| 45 | - Quiver (often ranged) actions for further use with `Q`. | 45 | - Quiver (often ranged) actions for further use with `Q`. |
| 46 | - You can fire ranged weapons manually with `f`, or auto-target your quiver | 46 | - You can fire ranged weapons manually with `f`, or auto-target your quiver with |
| 47 | with `p` or `Shift-Tab`. Throwing weapons can be thrown immediately, while | 47 | `p` or `Shift-Tab`. Throwing weapons can be thrown immediately, while |
| 48 | launchers (like bows) need to be wielded first. | 48 | launchers (like bows) need to be wielded first. |
| 49 | 49 | ||
| 50 | **Items and Inventory** | 50 | **Items and Inventory** |
| 51 | 51 | ||
| 52 | - View your inventory by pressing `i`. Most item related commands can also be | 52 | - View your inventory by pressing `i`. Most item related commands can also be |
| 53 | done with this menu. | 53 | done with this menu. |
| 54 | - You can wear amour with `W;` amour gives `AC`, while heavier body armour | 54 | - You can wear amour with `W;` amour gives `AC`, while heavier body armour |
| 55 | reduces `EV`. | 55 | reduces `EV`. |
| 56 | - Autoexplore will automatically pick up useful items, such as potions and | 56 | - Autoexplore will automatically pick up useful items, such as potions and |
| 57 | scrolls, if you aren't in danger. | 57 | scrolls, if you aren't in danger. |
| 58 | - You can read scrolls with `r` and drink ("quaff") potions with `q`. | 58 | - You can read scrolls with `r` and drink ("quaff") potions with `q`. |
| 59 | - Equipment items may have brands, with special properties. Branded equipment | 59 | - Equipment items may have brands, with special properties. Branded equipment is |
| 60 | is blue when unidentified. | 60 | blue when unidentified. |
| 61 | - Equipment items may be artifacts, often with unique properties, and are | 61 | - Equipment items may be artifacts, often with unique properties, and are |
| 62 | unmodifiable. They are written in white. | 62 | unmodifiable. They are written in white. |
| 63 | - You can evoke wands with `V`. | 63 | - You can evoke wands with `V`. |
| 64 | - You can put on jewelry with `P`, and remove it with `R`. | 64 | - You can put on jewelry with `P`, and remove it with `R`. |
| @@ -67,33 +67,32 @@ repository. | |||
| 67 | **Magic and Spellcasting** | 67 | **Magic and Spellcasting** |
| 68 | 68 | ||
| 69 | - Once you find a spellbook, you can memorize spells with `M`. | 69 | - Once you find a spellbook, you can memorize spells with `M`. |
| 70 | - You need to be the same XL as the spell's spell level in order to learn it, | 70 | - You need to be the same XL as the spell's spell level in order to learn it, in |
| 71 | in addition to training magical skill (to lower failure rate). | 71 | addition to training magical skill (to lower failure rate). |
| 72 | - Cast spells by pressing `z`, then the letter assigned to the spell. You may | 72 | - Cast spells by pressing `z`, then the letter assigned to the spell. You may |
| 73 | also Quiver a spell and then use it like a ranged weapon (with Shift-Tab). | 73 | also Quiver a spell and then use it like a ranged weapon (with Shift-Tab). |
| 74 | - You can view your memorized spells by pressing `I` (capital-i) or `z`. | 74 | - You can view your memorized spells by pressing `I` (capital-i) or `z`. |
| 75 | - Like HP, you can recover MP by resting (with 5). | 75 | - Like HP, you can recover MP by resting (with 5). |
| 76 | - Many spells can be positioned more effectively, or combined with other | 76 | - Many spells can be positioned more effectively, or combined with other spells, |
| 77 | spells, in order to get (more effective) use out of them. | 77 | in order to get (more effective) use out of them. |
| 78 | - Heavier body amour and shields hamper spellcasting. | 78 | - Heavier body amour and shields hamper spellcasting. |
| 79 | 79 | ||
| 80 | **Gods and Divine Abilities** | 80 | **Gods and Divine Abilities** |
| 81 | 81 | ||
| 82 | - You may look at a god's overview by praying at their altar (with `>` or `<`). | 82 | - You may look at a god's overview by praying at their altar (with `>` or `<`). |
| 83 | After praying, you can worship the god by pressing Enter afterwards. | 83 | After praying, you can worship the god by pressing Enter afterwards. |
| 84 | - Gods all have unique features about them. Trog, the god of the tutorial, is | 84 | - Gods all have unique features about them. Trog, the god of the tutorial, is |
| 85 | also the god of rage and bloodshed, and so despises spellcasting. | 85 | also the god of rage and bloodshed, and so despises spellcasting. |
| 86 | - Gods like and dislike different things. Most gods either like killing things | 86 | - Gods like and dislike different things. Most gods either like killing things |
| 87 | (like Trog) or exploring new areas (like Elyvilon), rewarding you piety | 87 | (like Trog) or exploring new areas (like Elyvilon), rewarding you piety |
| 88 | (divine favor) for doing so. | 88 | (divine favor) for doing so. |
| 89 | - You should learn to use and even rely on divine abilities often, as they are | 89 | - You should learn to use and even rely on divine abilities often, as they are |
| 90 | usually very strong. Trog's Berserk gives you 1.5x health, 1.5x speed (to | 90 | usually very strong. Trog's Berserk gives you 1.5x health, 1.5x speed (to all |
| 91 | all valid actions), and a big damage boost. Note that Berserk prevents most | 91 | valid actions), and a big damage boost. Note that Berserk prevents most |
| 92 | actions other than move and melee attack, and runs out very quickly if you | 92 | actions other than move and melee attack, and runs out very quickly if you |
| 93 | aren't attacking. And after berserk ends, you are slowed down and can't | 93 | aren't attacking. And after berserk ends, you are slowed down and can't |
| 94 | berserk again for a short time. | 94 | berserk again for a short time. |
| 95 | - In addition, the vast majority of abilities consume piety in the process. | 95 | - In addition, the vast majority of abilities consume piety in the process. |
| 96 | Regardless, this ability is very cheap, and the benefits are incredible, | 96 | Regardless, this ability is very cheap, and the benefits are incredible, so |
| 97 | so don't hold back! | 97 | don't hold back! |
| 98 | - Pressing `^` will let you view your current god, abilities, and piety. | 98 | - Pressing `^` will let you view your current god, abilities, and piety. |
| 99 | |||
diff --git a/content/notes/dcss-on-4k-displays.md b/content/notes/dcss-on-4k-displays.md index e3c6618..fd588db 100644 --- a/content/notes/dcss-on-4k-displays.md +++ b/content/notes/dcss-on-4k-displays.md | |||
| @@ -25,4 +25,6 @@ tile_sidebar_pixels = 64 | |||
| 25 | 25 | ||
| 26 | To zoom in and out in viewport, press `Ctrl+` and `Ctrl-` respectively. | 26 | To zoom in and out in viewport, press `Ctrl+` and `Ctrl-` respectively. |
| 27 | 27 | ||
| 28 | All the possible options are documented in the [Dungeon Crawl Stone Soup Options Guide](https://github.com/crawl/crawl/blob/master/crawl-ref/docs/options_guide.txt) file. | 28 | All the possible options are documented in the [Dungeon Crawl Stone Soup Options |
| 29 | Guide](https://github.com/crawl/crawl/blob/master/crawl-ref/docs/options_guide.txt) | ||
| 30 | file. | ||
diff --git a/content/notes/development-environments-with-nix.md b/content/notes/development-environments-with-nix.md index a6769ed..01844c9 100644 --- a/content/notes/development-environments-with-nix.md +++ b/content/notes/development-environments-with-nix.md | |||
| @@ -9,7 +9,8 @@ tags: [random] | |||
| 9 | 9 | ||
| 10 | Nix is amazing for making reproducible cross OS development environment. | 10 | Nix is amazing for making reproducible cross OS development environment. |
| 11 | 11 | ||
| 12 | First you need to [install Nix package manager](https://nixos.org/download.html). | 12 | First you need to [install Nix package |
| 13 | manager](https://nixos.org/download.html). | ||
| 13 | 14 | ||
| 14 | - Create a file `shell.nix` in your project folder. | 15 | - Create a file `shell.nix` in your project folder. |
| 15 | - In the section that has `python3` etc add programs you want to use. These can | 16 | - In the section that has `python3` etc add programs you want to use. These can |
diff --git a/content/notes/easy-time-took-in-bash.md b/content/notes/easy-time-took-in-bash.md index b65c090..e20e881 100644 --- a/content/notes/easy-time-took-in-bash.md +++ b/content/notes/easy-time-took-in-bash.md | |||
| @@ -7,7 +7,9 @@ draft: false | |||
| 7 | tags: [bash] | 7 | tags: [bash] |
| 8 | --- | 8 | --- |
| 9 | 9 | ||
| 10 | In Bash, the `$SECONDS` variable is a special variable that automatically keeps track of the number of seconds since the current shell or script started executing. It starts counting from the moment the script begins running. | 10 | In Bash, the `$SECONDS` variable is a special variable that automatically keeps |
| 11 | track of the number of seconds since the current shell or script started | ||
| 12 | executing. It starts counting from the moment the script begins running. | ||
| 11 | 13 | ||
| 12 | ```bash | 14 | ```bash |
| 13 | #!/bin/bash | 15 | #!/bin/bash |
diff --git a/content/notes/ewd-manuscripts-ebook.md b/content/notes/ewd-manuscripts-ebook.md index 1e496b9..5fc39b3 100644 --- a/content/notes/ewd-manuscripts-ebook.md +++ b/content/notes/ewd-manuscripts-ebook.md | |||
| @@ -8,8 +8,8 @@ tags: [random] | |||
| 8 | --- | 8 | --- |
| 9 | 9 | ||
| 10 | I love reading the original manuscripts of Edsger W. Dijkstra. They are | 10 | I love reading the original manuscripts of Edsger W. Dijkstra. They are |
| 11 | available online at the University of Texas at Austin website, but I also | 11 | available online at the University of Texas at Austin website, but I also found |
| 12 | found MOBI version. I converted it into ePub as well. | 12 | MOBI version. I converted it into ePub as well. |
| 13 | 13 | ||
| 14 | Downloads: | 14 | Downloads: |
| 15 | 15 | ||
diff --git a/content/notes/extending-dte-editor.md b/content/notes/extending-dte-editor.md index d23cbc7..161c104 100644 --- a/content/notes/extending-dte-editor.md +++ b/content/notes/extending-dte-editor.md | |||
| @@ -7,13 +7,14 @@ draft: false | |||
| 7 | tags: [dte] | 7 | tags: [dte] |
| 8 | --- | 8 | --- |
| 9 | 9 | ||
| 10 | [`dte`](https://craigbarnes.gitlab.io/dte/) is an interesting editor I started using | 10 | [`dte`](https://craigbarnes.gitlab.io/dte/) is an interesting editor I started |
| 11 | lately more and more. Since it is using [`execvp()`](https://linux.die.net/man/3/execvp) | 11 | using lately more and more. Since it is using |
| 12 | it can be easily extended. I needed comment/uncomment feature so I created a | 12 | [`execvp()`](https://linux.die.net/man/3/execvp) it can be easily extended. I |
| 13 | small utility that does this for me. Code lives on repository | 13 | needed comment/uncomment feature so I created a small utility that does this for |
| 14 | [dte extensions](https://git.mitjafelicijan.com/dte-extensions.git/about/) | 14 | me. Code lives on repository [dte |
| 15 | but this utilities can be used for whatever you want. Make sure you have | 15 | extensions](https://git.mitjafelicijan.com/dte-extensions.git/about/) but this |
| 16 | version 1.11 or above. | 16 | utilities can be used for whatever you want. Make sure you have version 1.11 or |
| 17 | above. | ||
| 17 | 18 | ||
| 18 | Next one will be invoking formatter based on the type of a file. | 19 | Next one will be invoking formatter based on the type of a file. |
| 19 | 20 | ||
diff --git a/content/notes/grep-to-less-maintain-colors.md b/content/notes/grep-to-less-maintain-colors.md index 9b797ee..6df2761 100644 --- a/content/notes/grep-to-less-maintain-colors.md +++ b/content/notes/grep-to-less-maintain-colors.md | |||
| @@ -7,16 +7,15 @@ draft: false | |||
| 7 | tags: [bash] | 7 | tags: [bash] |
| 8 | --- | 8 | --- |
| 9 | 9 | ||
| 10 | I often use `grep` to search for todo's in my code and other people's | 10 | I often use `grep` to search for todo's in my code and other people's code and |
| 11 | code and then pipe them in `less` and I missed having colors that grep | 11 | then pipe them in `less` and I missed having colors that grep outputs in `less`. |
| 12 | outputs in `less`. | ||
| 13 | 12 | ||
| 14 | - Grep's `--color=always` use markers to highlight the matching strings. | 13 | - Grep's `--color=always` use markers to highlight the matching strings. |
| 15 | - Less's `-R` option outputs "raw" control characters. | 14 | - Less's `-R` option outputs "raw" control characters. |
| 16 | 15 | ||
| 17 | You could use `alias grep='grep --color=always'` and `alias less='less | 16 | You could use `alias grep='grep --color=always'` and `alias less='less -R'` or |
| 18 | -R'` or create todo function in your `.bashrc` that accepts first argument | 17 | create todo function in your `.bashrc` that accepts first argument as search |
| 19 | as search string. | 18 | string. |
| 20 | 19 | ||
| 21 | ```sh | 20 | ```sh |
| 22 | # This is where the magic happens. | 21 | # This is where the magic happens. |
diff --git a/content/notes/install-plan9port-linux.md b/content/notes/install-plan9port-linux.md index 0ad83cf..b21c73b 100644 --- a/content/notes/install-plan9port-linux.md +++ b/content/notes/install-plan9port-linux.md | |||
| @@ -7,9 +7,10 @@ draft: false | |||
| 7 | tags: [plan9] | 7 | tags: [plan9] |
| 8 | --- | 8 | --- |
| 9 | 9 | ||
| 10 | Install Plan9port on Linux. This applies to [Plan9port](https://9fans.github.io/plan9port/). | 10 | Install Plan9port on Linux. This applies to |
| 11 | This is a port of many Plan 9 programs to Unix-like operating systems. Useful for | 11 | [Plan9port](https://9fans.github.io/plan9port/). This is a port of many Plan 9 |
| 12 | programs like `9term` and `rc`. | 12 | programs to Unix-like operating systems. Useful for programs like `9term` and |
| 13 | `rc`. | ||
| 13 | 14 | ||
| 14 | ```sh | 15 | ```sh |
| 15 | sudo apt-get install gcc libx11-dev libxt-dev libxext-dev libfontconfig1-dev | 16 | sudo apt-get install gcc libx11-dev libxt-dev libxext-dev libfontconfig1-dev |
diff --git a/content/notes/non-blocking-shell-exec-csharp.md b/content/notes/non-blocking-shell-exec-csharp.md index db40409..1904c4d 100644 --- a/content/notes/non-blocking-shell-exec-csharp.md +++ b/content/notes/non-blocking-shell-exec-csharp.md | |||
| @@ -32,8 +32,8 @@ private async Task executeCopyCommand() | |||
| 32 | } | 32 | } |
| 33 | ``` | 33 | ``` |
| 34 | 34 | ||
| 35 | Make sure that `async` is present in the function definition and `await` is | 35 | Make sure that `async` is present in the function definition and `await` is used |
| 36 | used in the method that calls `executeCopyCommand()`. | 36 | in the method that calls `executeCopyCommand()`. |
| 37 | 37 | ||
| 38 | ```c# | 38 | ```c# |
| 39 | private async void button_Click(object sender, EventArgs e) | 39 | private async void button_Click(object sender, EventArgs e) |
diff --git a/content/notes/presentations-with-markdown.md b/content/notes/presentations-with-markdown.md index f43faad..e2ba0a8 100644 --- a/content/notes/presentations-with-markdown.md +++ b/content/notes/presentations-with-markdown.md | |||
| @@ -7,8 +7,8 @@ draft: false | |||
| 7 | tags: [random] | 7 | tags: [random] |
| 8 | --- | 8 | --- |
| 9 | 9 | ||
| 10 | A simple way to make presentations without using desktop apps or using | 10 | A simple way to make presentations without using desktop apps or using online |
| 11 | online services is https://github.com/remarkjs/remark. | 11 | services is https://github.com/remarkjs/remark. |
| 12 | 12 | ||
| 13 | First create `index.html` and be sure you make changes to `config` variable. | 13 | First create `index.html` and be sure you make changes to `config` variable. |
| 14 | 14 | ||
diff --git a/content/posts/2011-01-13-most-likely-to-succeed-in-year-of-2011.md b/content/posts/2011-01-13-most-likely-to-succeed-in-year-of-2011.md index bdf965a..9fc484a 100644 --- a/content/posts/2011-01-13-most-likely-to-succeed-in-year-of-2011.md +++ b/content/posts/2011-01-13-most-likely-to-succeed-in-year-of-2011.md | |||
| @@ -5,31 +5,31 @@ date: 2011-01-13T12:00:00+02:00 | |||
| 5 | draft: false | 5 | draft: false |
| 6 | --- | 6 | --- |
| 7 | 7 | ||
| 8 | The year of 2010 was definitely the year of Geo-location. The market responded | 8 | The year of 2010 was definitely the year of Geo-location. The market responded |
| 9 | beautifully and lots of very cool services were launched. We all have to thank | 9 | beautifully and lots of very cool services were launched. We all have to thank |
| 10 | the mobile market for such extensive adoption. With new generations of mobile | 10 | the mobile market for such extensive adoption. With new generations of mobile |
| 11 | phones that are not only buffed with high-tech hardware but are also affordable. | 11 | phones that are not only buffed with high-tech hardware but are also affordable. |
| 12 | We can now manage tasks that were not so long time ago, almost Star Trek’ish. | 12 | We can now manage tasks that were not so long time ago, almost Star Trek’ish. |
| 13 | And all this had and has great influence on the destination to which we are | 13 | And all this had and has great influence on the destination to which we are |
| 14 | going now. | 14 | going now. |
| 15 | 15 | ||
| 16 | Reading all this articles about new innovation about new thriving technologies | 16 | Reading all this articles about new innovation about new thriving technologies |
| 17 | makes me wonder what’s the next step. The future is the mesh, like Lisa Gansky | 17 | makes me wonder what’s the next step. The future is the mesh, like Lisa Gansky |
| 18 | said in her book The Mesh. | 18 | said in her book The Mesh. |
| 19 | 19 | ||
| 20 | Many still have conservative views on distributed systems. The problems with | 20 | Many still have conservative views on distributed systems. The problems with |
| 21 | security of information. Fear of not controlling every aspect of information | 21 | security of information. Fear of not controlling every aspect of information |
| 22 | flow. I am very opened to distributed systems and heterogeneous applications, | 22 | flow. I am very opened to distributed systems and heterogeneous applications, |
| 23 | and I think this is the correct and best way to proceed. | 23 | and I think this is the correct and best way to proceed. |
| 24 | 24 | ||
| 25 | This year will definitely be about communication platforms. Mobile to mobile. | 25 | This year will definitely be about communication platforms. Mobile to mobile. |
| 26 | Machine to mobile and vice versa. All the tech is available and ready to put | 26 | Machine to mobile and vice versa. All the tech is available and ready to put |
| 27 | into action. Wireless is today’s new mantra. And the concept of semantic web | 27 | into action. Wireless is today’s new mantra. And the concept of semantic web is |
| 28 | is now ready for industry. | 28 | now ready for industry. |
| 29 | 29 | ||
| 30 | Applications and developers now can gain access to new layers of systems and | 30 | Applications and developers now can gain access to new layers of systems and can |
| 31 | can prepare and build solutions to meet the high quality needs of market. The | 31 | prepare and build solutions to meet the high quality needs of market. The speed |
| 32 | speed is everything now. | 32 | is everything now. |
| 33 | 33 | ||
| 34 | My vote goes to “Machine to Machine” and “Embedded Systems”! | 34 | My vote goes to “Machine to Machine” and “Embedded Systems”! |
| 35 | 35 | ||
diff --git a/content/posts/2012-03-09-led-technology-not-so-eco.md b/content/posts/2012-03-09-led-technology-not-so-eco.md index 6e5aab9..a683aec 100644 --- a/content/posts/2012-03-09-led-technology-not-so-eco.md +++ b/content/posts/2012-03-09-led-technology-not-so-eco.md | |||
| @@ -5,25 +5,25 @@ date: 2012-03-09T12:00:00+02:00 | |||
| 5 | draft: false | 5 | draft: false |
| 6 | --- | 6 | --- |
| 7 | 7 | ||
| 8 | There is a lot of talk about LED technology. It is beginning to infiltrate | 8 | There is a lot of talk about LED technology. It is beginning to infiltrate |
| 9 | industry at a fast rate, and it’s a challenge for designers and also engineers. | 9 | industry at a fast rate, and it’s a challenge for designers and also engineers. |
| 10 | I wondered when a weakness will be revealed. Then I stomped on an article | 10 | I wondered when a weakness will be revealed. Then I stomped on an article |
| 11 | talking about harm in using LED technology. It looks like this magical | 11 | talking about harm in using LED technology. It looks like this magical |
| 12 | technology is not so magical and eco-friendly. | 12 | technology is not so magical and eco-friendly. |
| 13 | 13 | ||
| 14 | A new study from the University of California indicates that LED lights | 14 | A new study from the University of California indicates that LED lights contain |
| 15 | contain toxic metals, and should be produced, used and disposed of carefully. | 15 | toxic metals, and should be produced, used and disposed of carefully. Besides |
| 16 | Besides the lead and nickel, the bulbs and their associated parts were also | 16 | the lead and nickel, the bulbs and their associated parts were also found to |
| 17 | found to contain arsenic, copper, and other metals that have been linked to | 17 | contain arsenic, copper, and other metals that have been linked to different |
| 18 | different cancers, neurological damage, kidney disease, hypertension, skin | 18 | cancers, neurological damage, kidney disease, hypertension, skin rashes and |
| 19 | rashes and other illnesses in humans, and to ecological damage in waterways. | 19 | other illnesses in humans, and to ecological damage in waterways. |
| 20 | 20 | ||
| 21 | Since then, I haven’t yet found any regulation for disposal of LED lights or | 21 | Since then, I haven’t yet found any regulation for disposal of LED lights or any |
| 22 | any other regulation or standard. This might be a problem in the future. And | 22 | other regulation or standard. This might be a problem in the future. And it is a |
| 23 | it is a massive drawback. This might have quite an impact on consumer market. | 23 | massive drawback. This might have quite an impact on consumer market. |
| 24 | 24 | ||
| 25 | Nevertheless, there is a potential, and I am sure the market will adapt. I | 25 | Nevertheless, there is a potential, and I am sure the market will adapt. I also |
| 26 | also hope I will be reading documents regarding solution for this concern soon. | 26 | hope I will be reading documents regarding solution for this concern soon. |
| 27 | 27 | ||
| 28 | **Additional resources:** | 28 | **Additional resources:** |
| 29 | 29 | ||
diff --git a/content/posts/2013-10-24-wireless-sensor-networks.md b/content/posts/2013-10-24-wireless-sensor-networks.md index dabdebc..fc5d372 100644 --- a/content/posts/2013-10-24-wireless-sensor-networks.md +++ b/content/posts/2013-10-24-wireless-sensor-networks.md | |||
| @@ -5,47 +5,45 @@ date: 2013-10-24T12:00:00+02:00 | |||
| 5 | draft: false | 5 | draft: false |
| 6 | --- | 6 | --- |
| 7 | 7 | ||
| 8 | Zigbee networks have this wonderful capability to self-heal, which means they | 8 | Zigbee networks have this wonderful capability to self-heal, which means they |
| 9 | can reorder connections between them if one of them is inoperable. This works | 9 | can reorder connections between them if one of them is inoperable. This works |
| 10 | our of the box when you deploy them. But you have to have in mind that | 10 | our of the box when you deploy them. But you have to have in mind that achieving |
| 11 | achieving this is not as easy as you would think. None of it is plug&play. | 11 | this is not as easy as you would think. None of it is plug&play. So to make |
| 12 | So to make your life a bit easier, here are some pointers which, I hope, | 12 | your life a bit easier, here are some pointers which, I hope, will help you. |
| 13 | will help you. | ||
| 14 | 13 | ||
| 15 | - Be careful when you are ordering your equipment abroad. There are many rules | 14 | - Be careful when you are ordering your equipment abroad. There are many rules |
| 16 | and regulations you need to comply before you get your Xbee radios. What they | 15 | and regulations you need to comply before you get your Xbee radios. What they |
| 17 | do is they wait until you prove that you won’t use the technology for some | 16 | do is they wait until you prove that you won’t use the technology for some |
| 18 | kind of evil take over control of the world project :). For this, they have | 17 | kind of evil take over control of the world project :). For this, they have |
| 19 | EAR (Export Administration Regulations) which basically means “This product | 18 | EAR (Export Administration Regulations) which basically means “This product |
| 20 | may require a license to export from the United States.”. | 19 | may require a license to export from the United States.”. |
| 21 | - I don’t know if this applies for every country, but when we purchased our | 20 | - I don’t know if this applies for every country, but when we purchased our Xbee |
| 22 | Xbee radios from Mouser, this was mandatory! What we needed to do was to | 21 | radios from Mouser, this was mandatory! What we needed to do was to print out |
| 23 | print out a form and write information about our company and send them a | 22 | a form and write information about our company and send them a copy via |
| 24 | copy via email. With this document, we proved that we are a legitimate | 23 | email. With this document, we proved that we are a legitimate company. |
| 25 | company. | 24 | - When you complete your purchase and send all the documentation, you are not |
| 26 | - When you complete your purchase and send all the documentation, you are not | 25 | clear yet. Then customs will take it from there :). There will be some |
| 27 | clear yet. Then customs will take it from there :). There will be some | 26 | additional costs. Before purchasing, make sure you have as much information |
| 28 | additional costs. Before purchasing, make sure you have as much information | ||
| 29 | about costs as possible. Because it can get costly in the end. | 27 | about costs as possible. Because it can get costly in the end. |
| 30 | - I suggest you use companies from your country. You can seriously cut your | 28 | - I suggest you use companies from your country. You can seriously cut your |
| 31 | costs. Here in Slovenia, the best option so far as I know is Farnell. And | 29 | costs. Here in Slovenia, the best option so far as I know is Farnell. And |
| 32 | based on my personal experience, they rock! All I need to say! | 30 | based on my personal experience, they rock! All I need to say! |
| 33 | - Make plans when ordering larger quantities. Do not, I say, do not make your | 31 | - Make plans when ordering larger quantities. Do not, I say, do not make your |
| 34 | orders in December! :) Believe me! You will have problems with stock they | 32 | orders in December! :) Believe me! You will have problems with stock they can |
| 35 | can provide for you. So, we were forced to buy some things from Mouser, | 33 | provide for you. So, we were forced to buy some things from Mouser, which was |
| 36 | which was extremely painful because of all the regulations you need to obey | 34 | extremely painful because of all the regulations you need to obey when |
| 37 | when importing goods from the USA. | 35 | importing goods from the USA. |
| 38 | - Make sure that firmware version on your Xbee radios is exactly the same! Do | 36 | - Make sure that firmware version on your Xbee radios is exactly the same! Do |
| 39 | not get creative!!! I propose using templates. You can get template by | 37 | not get creative!!! I propose using templates. You can get template by |
| 40 | exporting settings/profile in X-CTU application. Make sure you have enabled | 38 | exporting settings/profile in X-CTU application. Make sure you have enabled |
| 41 | “Upgrade firmware” so you can be sure each radio has the same firmware. | 39 | “Upgrade firmware” so you can be sure each radio has the same firmware. |
| 42 | - And again: make plans! Plan everything! In months advanced! You will thank | 40 | - And again: make plans! Plan everything! In months advanced! You will thank me |
| 43 | me later :) | 41 | later :) |
| 44 | - Test, test, test. Wireless networks can be tricky. | 42 | - Test, test, test. Wireless networks can be tricky. |
| 45 | 43 | ||
| 46 | If you are serious, I suggest you buy this book, Building Wireless Sensor | 44 | If you are serious, I suggest you buy this book, Building Wireless Sensor |
| 47 | Networks. You will get a glimpse of how networks work in lumens terms. It is | 45 | Networks. You will get a glimpse of how networks work in lumens terms. It is a |
| 48 | a good starting point for everybody who wants to build wireless networks. | 46 | good starting point for everybody who wants to build wireless networks. |
| 49 | 47 | ||
| 50 | **Additional resources:** | 48 | **Additional resources:** |
| 51 | 49 | ||
diff --git a/content/posts/2015-11-10-software-development-pitfalls.md b/content/posts/2015-11-10-software-development-pitfalls.md index 57e9736..b9edd19 100644 --- a/content/posts/2015-11-10-software-development-pitfalls.md +++ b/content/posts/2015-11-10-software-development-pitfalls.md | |||
| @@ -5,178 +5,176 @@ date: 2015-11-10T12:00:00+02:00 | |||
| 5 | draft: false | 5 | draft: false |
| 6 | --- | 6 | --- |
| 7 | 7 | ||
| 8 | Over the years I had the privilege to work on some very excited projects both | 8 | Over the years I had the privilege to work on some very excited projects both in |
| 9 | in software development field and also in electronics field and every experience | 9 | software development field and also in electronics field and every experience |
| 10 | taught me some invaluable lessons about how NOT TO approach development. And | 10 | taught me some invaluable lessons about how NOT TO approach development. And |
| 11 | through this post I will try to point out some absurd, outdated techniques I | 11 | through this post I will try to point out some absurd, outdated techniques I |
| 12 | find the most annoying and damaging during a development cycle. There will be | 12 | find the most annoying and damaging during a development cycle. There will be |
| 13 | swearing because this topic really gets on my nerves and I never coherently | 13 | swearing because this topic really gets on my nerves and I never coherently |
| 14 | tried to explain them in writing. So if I get heated up, please bear with me. | 14 | tried to explain them in writing. So if I get heated up, please bear with me. |
| 15 | 15 | ||
| 16 | As new methods of project management are emerging, underlying processes still | 16 | As new methods of project management are emerging, underlying processes still |
| 17 | stay old and outdated. This is mainly because we as people are unable to | 17 | stay old and outdated. This is mainly because we as people are unable to |
| 18 | completely shift away from these approaches. | 18 | completely shift away from these approaches. |
| 19 | 19 | ||
| 20 | I was always struggling with communication, and many times that cost me a | 20 | I was always struggling with communication, and many times that cost me a |
| 21 | relationship or two because I was not on the ball all the time. Through every | 21 | relationship or two because I was not on the ball all the time. Through every |
| 22 | experience, I became more convinced that I am the problem and never ever | 22 | experience, I became more convinced that I am the problem and never ever doubted |
| 23 | doubted that the problem may be that communication never evolved a single step | 23 | that the problem may be that communication never evolved a single step from |
| 24 | from emails. And if you think for a second, not many things have changed around | 24 | emails. And if you think for a second, not many things have changed around this |
| 25 | this topic. We just have different representations of email (message boards, | 25 | topic. We just have different representations of email (message boards, chats, |
| 26 | chats, project management tools). And I believe this is the real issue we are | 26 | project management tools). And I believe this is the real issue we are facing |
| 27 | facing now. | 27 | now. |
| 28 | 28 | ||
| 29 | There are many articles written about hyper connectivity and the effects that | 29 | There are many articles written about hyper connectivity and the effects that |
| 30 | are a direct result of it. But mainstream does nothing towards it. We are just | 30 | are a direct result of it. But mainstream does nothing towards it. We are just |
| 31 | putting out fires, and we do nothing to prevent it. I am certain this will be | 31 | putting out fires, and we do nothing to prevent it. I am certain this will be a |
| 32 | a major source of grief in coming years. And what we all can do to avoid this | 32 | major source of grief in coming years. And what we all can do to avoid this is |
| 33 | is to change our mindset and experiment on our communication skills, | 33 | to change our mindset and experiment on our communication skills, development |
| 34 | development approaches. We need to maximize possible output that a person can | 34 | approaches. We need to maximize possible output that a person can give. And to |
| 35 | give. And to achieve this we need to listen to them, encourage them. I know | 35 | achieve this we need to listen to them, encourage them. I know that not |
| 36 | that not everybody is a naturally born leader, but with enough practice and | 36 | everybody is a naturally born leader, but with enough practice and encouragement |
| 37 | encouragement they also can become active participants in leadership. | 37 | they also can become active participants in leadership. |
| 38 | 38 | ||
| 39 | There are many talks now about methodologies such as Scrum, Kanban, Cleanroom | 39 | There are many talks now about methodologies such as Scrum, Kanban, Cleanroom |
| 40 | and they all fucking piss me of :). These are all boxes that imprison people | 40 | and they all fucking piss me of :). These are all boxes that imprison people and |
| 41 | and take away their freedom of thought. This is a straightforward | 41 | take away their freedom of thought. This is a straightforward mindfuck / |
| 42 | mindfuck / amputation of creativity. | 42 | amputation of creativity. |
| 43 | 43 | ||
| 44 | Let me list a couple of things that I find really destructive and bad for a | 44 | Let me list a couple of things that I find really destructive and bad for a |
| 45 | project and in a long run company. | 45 | project and in a long run company. |
| 46 | 46 | ||
| 47 | ## Ping emails | 47 | ## Ping emails |
| 48 | 48 | ||
| 49 | Ping emails are emails you have to write as soon as you receive an email. Its | 49 | Ping emails are emails you have to write as soon as you receive an email. Its |
| 50 | sole purpose is to inform the sender that you received their email, and you | 50 | sole purpose is to inform the sender that you received their email, and you are |
| 51 | are working on it. Its result is only to calm down the sender that their task | 51 | working on it. Its result is only to calm down the sender that their task is |
| 52 | is being dealt with. It’s intent basically is, I did my job by sending you | 52 | being dealt with. It’s intent basically is, I did my job by sending you this |
| 53 | this email, so I am on clear grounds. I categorize this email as fuck you email. | 53 | email, so I am on clear grounds. I categorize this email as fuck you email. |
| 54 | This is one of the most irritating types of emails I need to write. This is | 54 | This is one of the most irritating types of emails I need to write. This is the |
| 55 | the ultimate control freak show you can experience, and it gives the sender a | 55 | ultimate control freak show you can experience, and it gives the sender a false |
| 56 | false feeling of control. Newsflash: We do not live in 1982 where there was a | 56 | feeling of control. Newsflash: We do not live in 1982 where there was a |
| 57 | possibility that email never reached the destination. I really hate this from | 57 | possibility that email never reached the destination. I really hate this from |
| 58 | the bottom of my heart. | 58 | the bottom of my heart. |
| 59 | 59 | ||
| 60 | They should be like: “Yes, I am fucking alive, and I am at your service my | 60 | They should be like: “Yes, I am fucking alive, and I am at your service my |
| 61 | leash!”. I guess if I would reply like this, I wouldn’t have to write any | 61 | leash!”. I guess if I would reply like this, I wouldn’t have to write any more |
| 62 | more of this kind of messages. | 62 | of this kind of messages. |
| 63 | 63 | ||
| 64 | ## Everybody is a project manager | 64 | ## Everybody is a project manager |
| 65 | 65 | ||
| 66 | Well, this is a tough one. I noticed that as soon as you let people to give | 66 | Well, this is a tough one. I noticed that as soon as you let people to give |
| 67 | their suggestions, you are basically screwed. There is a truth in the saying: | 67 | their suggestions, you are basically screwed. There is a truth in the saying: |
| 68 | “Give low expectations and deliver little more than you promised.”. | 68 | “Give low expectations and deliver little more than you promised.”. |
| 69 | 69 | ||
| 70 | People tend to take a role of a manager as soon as they are presented with an | 70 | People tend to take a role of a manager as soon as they are presented with an |
| 71 | opportunity. And by getting angry at them, you only provoke yourself. They are | 71 | opportunity. And by getting angry at them, you only provoke yourself. They are |
| 72 | not at fault. You just need to tell them they are only giving suggestions and | 72 | not at fault. You just need to tell them they are only giving suggestions and |
| 73 | not tasks at the beginning and everything will be alright. But if you give | 73 | not tasks at the beginning and everything will be alright. But if you give them |
| 74 | them a feeling that they are in control, you will have immense problems | 74 | a feeling that they are in control, you will have immense problems explaining |
| 75 | explaining why their features are not in current release. | 75 | why their features are not in current release. |
| 76 | 76 | ||
| 77 | Project mission must be always leading project requirements and any deviation | 77 | Project mission must be always leading project requirements and any deviation |
| 78 | from it will result in major project butchering. And by this, I mean that the | 78 | from it will result in major project butchering. And by this, I mean that the |
| 79 | project will get its own path, and you will be left with half done software | 79 | project will get its own path, and you will be left with half done software that |
| 80 | that helps nobody. Clear mission goals and clean execution will allow you to | 80 | helps nobody. Clear mission goals and clean execution will allow you to develop |
| 81 | develop software will clear intent. | 81 | software will clear intent. |
| 82 | 82 | ||
| 83 | ## We are never wrong | 83 | ## We are never wrong |
| 84 | 84 | ||
| 85 | I find this type of arrogance the worst. We must always conduct ourselves that | 85 | I find this type of arrogance the worst. We must always conduct ourselves that |
| 86 | we are infallible and cannot make mistakes. As soon as a procedure or process | 86 | we are infallible and cannot make mistakes. As soon as a procedure or process is |
| 87 | is established, there is no room for changes or improvements. This is the most | 87 | established, there is no room for changes or improvements. This is the most |
| 88 | idiotic thing someone can say of think. I think that processes need to involve | 88 | idiotic thing someone can say of think. I think that processes need to involve |
| 89 | and change over time. This is imperative and need to have in your organization | 89 | and change over time. This is imperative and need to have in your organization |
| 90 | if you want to improve and develop company. We all need to grow balls and change | 90 | if you want to improve and develop company. We all need to grow balls and change |
| 91 | everything in order to adapt to current situations. Being a prisoner of | 91 | everything in order to adapt to current situations. Being a prisoner of |
| 92 | predefined processes kills creativity. | 92 | predefined processes kills creativity. |
| 93 | 93 | ||
| 94 | I am constantly trying new software for project managing and communication. | 94 | I am constantly trying new software for project managing and communication. I |
| 95 | I believe every team has its own dynamic, and it needs to be discovered | 95 | believe every team has its own dynamic, and it needs to be discovered |
| 96 | organically and naturally through many experiments. By putting the team in a | 96 | organically and naturally through many experiments. By putting the team in a |
| 97 | box, you are amputating their creativity and therefore minimizing their | 97 | box, you are amputating their creativity and therefore minimizing their |
| 98 | potential. But if you talk to an executive, you will mainly find archetypical | 98 | potential. But if you talk to an executive, you will mainly find archetypical |
| 99 | thinking and a strong need to compartmentalize everything from business | 99 | thinking and a strong need to compartmentalize everything from business |
| 100 | processes to resource management. And this type of management that often | 100 | processes to resource management. And this type of management that often |
| 101 | displays micromanagement techniques only works for short periods (couple of | 101 | displays micromanagement techniques only works for short periods (couple of |
| 102 | years) and then employees either leave the company or become basically retarded | 102 | years) and then employees either leave the company or become basically retarded |
| 103 | drones on autopilot. | 103 | drones on autopilot. |
| 104 | 104 | ||
| 105 | ## Micromanaging | 105 | ## Micromanaging |
| 106 | 106 | ||
| 107 | This basically implies that everybody on the team is an idiot who needs to | 107 | This basically implies that everybody on the team is an idiot who needs to have |
| 108 | have a to-do list that they cannot write themselves. How about spoon-feeding | 108 | a to-do list that they cannot write themselves. How about spoon-feeding the team |
| 109 | the team at launch because besides the team leader, everybody must be a | 109 | at launch because besides the team leader, everybody must be a retarded idiot at |
| 110 | retarded idiot at best? | 110 | best? |
| 111 | 111 | ||
| 112 | I prefer milestones as they give developers much more freedom and creativity | 112 | I prefer milestones as they give developers much more freedom and creativity in |
| 113 | in developing and not waste their time checking some bizarre to-do list that | 113 | developing and not waste their time checking some bizarre to-do list that was |
| 114 | was not even thought through. Projects constantly change throughout the | 114 | not even thought through. Projects constantly change throughout the development |
| 115 | development cycle, and all you are left at the end is a list of unchecked tasks | 115 | cycle, and all you are left at the end is a list of unchecked tasks and the |
| 116 | and the wrath of management why they are not completed. Best WTF moment! | 116 | wrath of management why they are not completed. Best WTF moment! |
| 117 | 117 | ||
| 118 | ## Human contact — no need for it! | 118 | ## Human contact — no need for it! |
| 119 | 119 | ||
| 120 | We are vigorously trying to eliminate physical contact by replacing short | 120 | We are vigorously trying to eliminate physical contact by replacing short |
| 121 | meetings with software, with no regards that we are not machines. Many times | 121 | meetings with software, with no regards that we are not machines. Many times a |
| 122 | a simple 5-min meeting at morning can solve most of the problems. In rapid | 122 | simple 5-min meeting at morning can solve most of the problems. In rapid |
| 123 | development, short bursts of man to man communication is possibly the best | 123 | development, short bursts of man to man communication is possibly the best way |
| 124 | way to go. | 124 | to go. |
| 125 | 125 | ||
| 126 | We now have all this software available, and all what we get out of it is a | 126 | We now have all this software available, and all what we get out of it is a |
| 127 | giant clusterfuck. An obstacle and not a solution. So, why we still use them? | 127 | giant clusterfuck. An obstacle and not a solution. So, why we still use them? |
| 128 | 128 | ||
| 129 | ## MVP is killing innovation | 129 | ## MVP is killing innovation |
| 130 | 130 | ||
| 131 | Many will disagree with me on this one, but I stand strong by this statement. | 131 | Many will disagree with me on this one, but I stand strong by this statement. |
| 132 | What I noticed in my experience that all this buzz words around us only | 132 | What I noticed in my experience that all this buzz words around us only mislead |
| 133 | mislead and capture us in a circle of solving issues that already have a | 133 | and capture us in a circle of solving issues that already have a solution, but |
| 134 | solution, but we are unable to see it without using some fancy word for it. | 134 | we are unable to see it without using some fancy word for it. |
| 135 | 135 | ||
| 136 | The toughest thing to do for a developer is to minimize requirements. Well, | 136 | The toughest thing to do for a developer is to minimize requirements. Well, this |
| 137 | this is though only for bad developers. Yes, I said it. There are many types | 137 | is though only for bad developers. Yes, I said it. There are many types of |
| 138 | of developers out there. And those unable to minimize feature scope are the | 138 | developers out there. And those unable to minimize feature scope are the ones |
| 139 | ones you don’t need on your team. Their only goal is to solve problems that | 139 | you don’t need on your team. Their only goal is to solve problems that exist |
| 140 | exist only in their heads. And then you have to argue with them, and waste | 140 | only in their heads. And then you have to argue with them, and waste energy on |
| 141 | energy on them, instead of developing your awesome product. They are a cancer | 141 | them, instead of developing your awesome product. They are a cancer and I |
| 142 | and I suggest you cut them off. | 142 | suggest you cut them off. |
| 143 | 143 | ||
| 144 | MVP as an idea is great, but sadly people don’t understand underlying | 144 | MVP as an idea is great, but sadly people don’t understand underlying |
| 145 | philosophy, and they spent too much time focusing and fixating on something | 145 | philosophy, and they spent too much time focusing and fixating on something that |
| 146 | that every sane person with normal IQ will understand without some made up | 146 | every sane person with normal IQ will understand without some made up |
| 147 | acronym. And the result is a lot of talking and barely no execution. | 147 | acronym. And the result is a lot of talking and barely no execution. |
| 148 | 148 | ||
| 149 | Well, MVP is not directly killing innovation, but stupid people do when they | 149 | Well, MVP is not directly killing innovation, but stupid people do when they try |
| 150 | try to understand it. | 150 | to understand it. |
| 151 | 151 | ||
| 152 | ## Pressure wasteland | 152 | ## Pressure wasteland |
| 153 | 153 | ||
| 154 | You must never allow to be pressured into confirming a deadline if you are not | 154 | You must never allow to be pressured into confirming a deadline if you are not |
| 155 | confident. We often feel a need that we are in service of others, which is | 155 | confident. We often feel a need that we are in service of others, which is true |
| 156 | true to some extent. But it is also true that others are in service to us to | 156 | to some extent. But it is also true that others are in service to us to some |
| 157 | some extent. And we forget this all the time. We are all pressured all the | 157 | extent. And we forget this all the time. We are all pressured all the time to |
| 158 | time to make decisions just to calm other people down. And when they leave | 158 | make decisions just to calm other people down. And when they leave your office |
| 159 | your office you experience WTF moment :) How the hell did they manage to | 159 | you experience WTF moment :) How the hell did they manage to fuck me up again? |
| 160 | fuck me up again? | 160 | |
| 161 | 161 | People need to realize that the more pressure you put on somebody, the less they | |
| 162 | People need to realize that the more pressure you put on somebody, the less | 162 | will be able to do. So 5-min update email requests will only resolve in mental |
| 163 | they will be able to do. So 5-min update email requests will only resolve in | 163 | breakdown and inability to work that day. Constant poking is probably the only |
| 164 | mental breakdown and inability to work that day. Constant poking is probably | 164 | thing I lose my mind instantly. For all you that are doing this: “Stop bothering |
| 165 | the only thing I lose my mind instantly. For all you that are doing this: | 165 | us with your insecurities and let us do our job. We will do it quicker and |
| 166 | “Stop bothering us with your insecurities and let us do our job. We will do | 166 | better without you breathing down our necks.” |
| 167 | it quicker and better without you breathing down our necks.” | ||
| 168 | 167 | ||
| 169 | If this happens to me, I end up with no energy at the end. Don’t you get it? | 168 | If this happens to me, I end up with no energy at the end. Don’t you get it? |
| 170 | You will get much more from and out of me if you ask me like a human person | 169 | You will get much more from and out of me if you ask me like a human person and |
| 171 | and not your personal butler. On a long run, you are destroying your | 170 | not your personal butler. On a long run, you are destroying your relationships |
| 172 | relationships and nobody would want to work with you. Your schizophrenic | 171 | and nobody would want to work with you. Your schizophrenic approach will damage |
| 173 | approach will damage only you in a long run. Nobody is anybody’s property. | 172 | only you in a long run. Nobody is anybody’s property. |
| 174 | 173 | ||
| 175 | ## Conclusion | 174 | ## Conclusion |
| 176 | 175 | ||
| 177 | I am guilty of many things described in this post. And I find it hard sometimes | 176 | I am guilty of many things described in this post. And I find it hard sometimes |
| 178 | to acknowledge this. And I lie to myself and try vigorously to find some | 177 | to acknowledge this. And I lie to myself and try vigorously to find some |
| 179 | explanation why I do these things. There is always space for growth. And | 178 | explanation why I do these things. There is always space for growth. And maybe |
| 180 | maybe you will also find some of yourself in this post and realize what needs | 179 | you will also find some of yourself in this post and realize what needs to |
| 181 | to change for you to evolve. | 180 | change for you to evolve. |
| 182 | |||
diff --git a/content/posts/2017-03-07-golang-profiling-simplified.md b/content/posts/2017-03-07-golang-profiling-simplified.md index 7eee2dd..4bd18b2 100644 --- a/content/posts/2017-03-07-golang-profiling-simplified.md +++ b/content/posts/2017-03-07-golang-profiling-simplified.md | |||
| @@ -6,34 +6,34 @@ draft: false | |||
| 6 | --- | 6 | --- |
| 7 | 7 | ||
| 8 | Many posts have been written regarding profiling in Golang and I haven’t found | 8 | Many posts have been written regarding profiling in Golang and I haven’t found |
| 9 | proper tutorial regarding this. Almost all of them are missing some part of | 9 | proper tutorial regarding this. Almost all of them are missing some part of |
| 10 | important information and it gets pretty frustrating when you have a deadline | 10 | important information and it gets pretty frustrating when you have a deadline |
| 11 | and are not finding simple distilled solution. | 11 | and are not finding simple distilled solution. |
| 12 | 12 | ||
| 13 | Nevertheless, after searching and experimenting I have found a solution that | 13 | Nevertheless, after searching and experimenting I have found a solution that |
| 14 | works for me and probably should also for you. | 14 | works for me and probably should also for you. |
| 15 | 15 | ||
| 16 | ## Where are my pprof files? | 16 | ## Where are my pprof files? |
| 17 | 17 | ||
| 18 | By default pprof files are generated in /tmp/ folder. You can override folder | 18 | By default pprof files are generated in /tmp/ folder. You can override folder |
| 19 | where this files are generated programmatically in your golang code as we will | 19 | where this files are generated programmatically in your golang code as we will |
| 20 | see below in example. | 20 | see below in example. |
| 21 | 21 | ||
| 22 | ## Why is my CPU profile empty? | 22 | ## Why is my CPU profile empty? |
| 23 | 23 | ||
| 24 | I have found out that sometimes CPU profile is empty because program was not | 24 | I have found out that sometimes CPU profile is empty because program was not |
| 25 | executing long enough. Programs, that execute too quickly don’t produce pprof | 25 | executing long enough. Programs, that execute too quickly don’t produce pprof |
| 26 | file in my cases. Well, file is generated but only contains 4KB of information. | 26 | file in my cases. Well, file is generated but only contains 4KB of information. |
| 27 | 27 | ||
| 28 | ## Profiling | 28 | ## Profiling |
| 29 | 29 | ||
| 30 | As you can see from examples we are executing dummy_benchmark functions to | 30 | As you can see from examples we are executing dummy_benchmark functions to |
| 31 | ensure some sort of execution. Memory profiling can be done without such a | 31 | ensure some sort of execution. Memory profiling can be done without such a |
| 32 | “complex” function. But CPU profiling needs it. | 32 | “complex” function. But CPU profiling needs it. |
| 33 | 33 | ||
| 34 | Both memory and CPU profiling examples are almost the same. Only parameters | 34 | Both memory and CPU profiling examples are almost the same. Only parameters in |
| 35 | in main function when calling profile.Start are different. When we set | 35 | main function when calling profile.Start are different. When we set |
| 36 | profile.ProfilePath(“.”) we tell profiler to store pprof files in the same | 36 | profile.ProfilePath(“.”) we tell profiler to store pprof files in the same |
| 37 | folder as our program. | 37 | folder as our program. |
| 38 | 38 | ||
| 39 | ### Memory profiling | 39 | ### Memory profiling |
diff --git a/content/posts/2017-04-17-what-i-ve-learned-developing-ad-server.md b/content/posts/2017-04-17-what-i-ve-learned-developing-ad-server.md index 1b9be06..bb98efd 100644 --- a/content/posts/2017-04-17-what-i-ve-learned-developing-ad-server.md +++ b/content/posts/2017-04-17-what-i-ve-learned-developing-ad-server.md | |||
| @@ -5,10 +5,10 @@ date: 2017-04-17T12:00:00+02:00 | |||
| 5 | draft: false | 5 | draft: false |
| 6 | --- | 6 | --- |
| 7 | 7 | ||
| 8 | For the past year and half I have been developing native advertising server | 8 | For the past year and half I have been developing native advertising server that |
| 9 | that contextually matches ads and displays them in different template forms | 9 | contextually matches ads and displays them in different template forms on |
| 10 | on variety of websites. This project grew from serving thousands of ads per | 10 | variety of websites. This project grew from serving thousands of ads per day to |
| 11 | day to millions. | 11 | millions. |
| 12 | 12 | ||
| 13 | The system is made from couple of core components: | 13 | The system is made from couple of core components: |
| 14 | 14 | ||
| @@ -16,56 +16,56 @@ The system is made from couple of core components: | |||
| 16 | - Utils - cronjobs and queue management tools, | 16 | - Utils - cronjobs and queue management tools, |
| 17 | - Dashboard UI. | 17 | - Dashboard UI. |
| 18 | 18 | ||
| 19 | Initial release was using [MongoDB](https://www.mongodb.com/) for full-text | 19 | Initial release was using [MongoDB](https://www.mongodb.com/) for full-text |
| 20 | search but was later replaced by [Elasticsearch](https://www.elastic.co/) | 20 | search but was later replaced by [Elasticsearch](https://www.elastic.co/) for |
| 21 | for better CPU utilization and better search performance. This provided us | 21 | better CPU utilization and better search performance. This provided us with many |
| 22 | with many amazing functionalities of [Elasticsearch](https://www.elastic.co/). | 22 | amazing functionalities of [Elasticsearch](https://www.elastic.co/). You should |
| 23 | You should check it out if you do any search related operations. | 23 | check it out if you do any search related operations. |
| 24 | 24 | ||
| 25 | Because the premise of the server is to provide native ad experience, they | 25 | Because the premise of the server is to provide native ad experience, they are |
| 26 | are rendered on the client side via simple templating engine. This ensures | 26 | rendered on the client side via simple templating engine. This ensures that ads |
| 27 | that ads can be displayed number of different ways based on the visual style | 27 | can be displayed number of different ways based on the visual style of the |
| 28 | of the page. And this makes JavaScript client library quite complex. | 28 | page. And this makes JavaScript client library quite complex. |
| 29 | 29 | ||
| 30 | So now that you know basic information about the product lets get into the | 30 | So now that you know basic information about the product lets get into the |
| 31 | lessons we learned. | 31 | lessons we learned. |
| 32 | 32 | ||
| 33 | ## Aggregate everything | 33 | ## Aggregate everything |
| 34 | 34 | ||
| 35 | After beta version was released everything (impressions, clicks, etc) was | 35 | After beta version was released everything (impressions, clicks, etc) was |
| 36 | written in nanosecond resolution in the database. At that time we were using | 36 | written in nanosecond resolution in the database. At that time we were using |
| 37 | [PostgreSQL](https://www.postgresql.org/) and database quickly grew way above | 37 | [PostgreSQL](https://www.postgresql.org/) and database quickly grew way above |
| 38 | 200GB in disk space. And that was problematic. Statistics took disturbingly | 38 | 200GB in disk space. And that was problematic. Statistics took disturbingly long |
| 39 | long time to aggregate. Also using indexes on stats table in database was no | 39 | time to aggregate. Also using indexes on stats table in database was no help |
| 40 | help after we reached 500 million datapoints. | 40 | after we reached 500 million datapoints. |
| 41 | 41 | ||
| 42 | > There is a marketing product information and there is real life experience. | 42 | > There is a marketing product information and there is real life experience. |
| 43 | And the tend to be quite the opposite. | 43 | And the tend to be quite the opposite. |
| 44 | 44 | ||
| 45 | This was the reason that now everything is aggregated on daily basis and this | 45 | This was the reason that now everything is aggregated on daily basis and this |
| 46 | data is then fed to Elastic in form of daily summary. With this we achieved we | 46 | data is then fed to Elastic in form of daily summary. With this we achieved we |
| 47 | can now track many more dimensions such as zone, channel and platform information. | 47 | can now track many more dimensions such as zone, channel and platform |
| 48 | And with this information we can now adapt occurrences of ads on specific | 48 | information. And with this information we can now adapt occurrences of ads on |
| 49 | places more precisely. | 49 | specific places more precisely. |
| 50 | 50 | ||
| 51 | We have also adapted [Redis](https://redis.io/) as a full-time citizen in our | 51 | We have also adapted [Redis](https://redis.io/) as a full-time citizen in our |
| 52 | stack. Because Redis also stores information on a local disk we have some sort | 52 | stack. Because Redis also stores information on a local disk we have some sort |
| 53 | of backup if server would accidentally suffer some failure. | 53 | of backup if server would accidentally suffer some failure. |
| 54 | 54 | ||
| 55 | All the real-time statistics for ad serving and redirecting is presented as | 55 | All the real-time statistics for ad serving and redirecting is presented as |
| 56 | counters in Redis instance and daily extracted and pushed to Elastic. | 56 | counters in Redis instance and daily extracted and pushed to Elastic. |
| 57 | 57 | ||
| 58 | ## Measure everything | 58 | ## Measure everything |
| 59 | 59 | ||
| 60 | The thing about software is that we really don't know how well it is performing | 60 | The thing about software is that we really don't know how well it is performing |
| 61 | under load until such load is presented. When testing locally everything is | 61 | under load until such load is presented. When testing locally everything is fine |
| 62 | fine but when on production things tend to fall apart. | 62 | but when on production things tend to fall apart. |
| 63 | 63 | ||
| 64 | As a solution for this we are measuring everything we can. Function execution | 64 | As a solution for this we are measuring everything we can. Function execution |
| 65 | time (by encapsulating functions with timers), server performance (cpu, memory, | 65 | time (by encapsulating functions with timers), server performance (cpu, memory, |
| 66 | disk, etc), Nginx and [uWSGI](https://uwsgi-docs.readthedocs.io/) performance. | 66 | disk, etc), Nginx and [uWSGI](https://uwsgi-docs.readthedocs.io/) performance. |
| 67 | We sacrifice a bit of performance for the sake of this information. And we | 67 | We sacrifice a bit of performance for the sake of this information. And we store |
| 68 | store all this information for later analysis. | 68 | all this information for later analysis. |
| 69 | 69 | ||
| 70 | **Example of function execution time** | 70 | **Example of function execution time** |
| 71 | 71 | ||
| @@ -99,27 +99,28 @@ store all this information for later analysis. | |||
| 99 | } | 99 | } |
| 100 | ``` | 100 | ``` |
| 101 | 101 | ||
| 102 | We have also started profiling with [cProfile](https://pymotw.com/2/profile/) | 102 | We have also started profiling with [cProfile](https://pymotw.com/2/profile/) |
| 103 | and then visualizing with [KCachegrind](http://kcachegrind.sourceforge.net/). | 103 | and then visualizing with [KCachegrind](http://kcachegrind.sourceforge.net/). |
| 104 | This provides much more detailed look into code execution. | 104 | This provides much more detailed look into code execution. |
| 105 | 105 | ||
| 106 | ## Cache control is your friend | 106 | ## Cache control is your friend |
| 107 | 107 | ||
| 108 | Because we use Javascript library for rendering ads we rely on this script | 108 | Because we use Javascript library for rendering ads we rely on this script |
| 109 | extensively and when in need we need to be able to change behavior of the | 109 | extensively and when in need we need to be able to change behavior of the script |
| 110 | script quickly. | 110 | quickly. |
| 111 | 111 | ||
| 112 | In our case we can not simply replace javascript url in html code. It usually | 112 | In our case we can not simply replace javascript url in html code. It usually |
| 113 | takes a day or two for the guys who maintain sites to change code or add | 113 | takes a day or two for the guys who maintain sites to change code or add |
| 114 | ?ver=xxx attribute. And this makes rapid deployment and testing very difficult | 114 | ?ver=xxx attribute. And this makes rapid deployment and testing very difficult |
| 115 | and time consuming. There is a limitation of how much you can test locally. | 115 | and time consuming. There is a limitation of how much you can test locally. |
| 116 | 116 | ||
| 117 | We are now in the process of integrating [Google Tag Manager](https://www.google.com/analytics/tag-manager/) | 117 | We are now in the process of integrating [Google Tag |
| 118 | but couple of websites are developed on ASP.net platform that have some | 118 | Manager](https://www.google.com/analytics/tag-manager/) but couple of websites |
| 119 | problems with tag manager. With a solution below we are certain that we are | 119 | are developed on ASP.net platform that have some problems with tag manager. With |
| 120 | serving latest version of the script. | 120 | a solution below we are certain that we are serving latest version of the |
| 121 | script. | ||
| 121 | 122 | ||
| 122 | And it only takes one mistake and users have the script cached and in case of | 123 | And it only takes one mistake and users have the script cached and in case of |
| 123 | caching it for 1 year you probably know where the problem is. | 124 | caching it for 1 year you probably know where the problem is. |
| 124 | 125 | ||
| 125 | ```nginx | 126 | ```nginx |
| @@ -143,10 +144,10 @@ location /static/ { | |||
| 143 | } | 144 | } |
| 144 | ``` | 145 | ``` |
| 145 | 146 | ||
| 146 | Also be careful when redirecting to url in your python code. We noticed that | 147 | Also be careful when redirecting to url in your python code. We noticed that if |
| 147 | if we didn't precisely setup cache control and expire headers in response we | 148 | we didn't precisely setup cache control and expire headers in response we didn't |
| 148 | didn't get the request on the server and therefore couldn't measure clicks. | 149 | get the request on the server and therefore couldn't measure clicks. So when |
| 149 | So when redirecting do as follows and there will be no problems. | 150 | redirecting do as follows and there will be no problems. |
| 150 | 151 | ||
| 151 | ```python | 152 | ```python |
| 152 | # python ➜ bottlepy web micro-framework | 153 | # python ➜ bottlepy web micro-framework |
| @@ -157,42 +158,41 @@ response.set_header("Location", url) | |||
| 157 | return response | 158 | return response |
| 158 | ``` | 159 | ``` |
| 159 | 160 | ||
| 160 | > Cache control in browsers is quite aggressive and you need to be precise | 161 | > Cache control in browsers is quite aggressive and you need to be precise to |
| 161 | to avoid future problems. We learned that lesson the hard way. | 162 | avoid future problems. We learned that lesson the hard way. |
| 162 | 163 | ||
| 163 | ## Learn NGINX | 164 | ## Learn NGINX |
| 164 | 165 | ||
| 165 | When deciding on a web server we went with Nginx as a reverse proxy for our | 166 | When deciding on a web server we went with Nginx as a reverse proxy for our |
| 166 | applications. We adapted micro-service oriented architecture early in the | 167 | applications. We adapted micro-service oriented architecture early in the |
| 167 | project to ensure when we scale we can easily add additional servers to our | 168 | project to ensure when we scale we can easily add additional servers to our |
| 168 | cluster. And Nginx was crucial to perform load balancing and static content | 169 | cluster. And Nginx was crucial to perform load balancing and static content |
| 169 | delivery. | 170 | delivery. |
| 170 | 171 | ||
| 171 | At first our config file was quite simple and later grew larger. After patching | 172 | At first our config file was quite simple and later grew larger. After patching |
| 172 | and adding new settings I sat down and learned more about the guts of Nginx. | 173 | and adding new settings I sat down and learned more about the guts of Nginx. |
| 173 | This proved to be very useful and we were able to squeeze much more out of our | 174 | This proved to be very useful and we were able to squeeze much more out of our |
| 174 | setup. So I advise you to take your time and read through the | 175 | setup. So I advise you to take your time and read through the |
| 175 | [documentation](https://nginx.org/en/docs/). This saved us a lot of headache. | 176 | [documentation](https://nginx.org/en/docs/). This saved us a lot of headache. |
| 176 | Googling for solutions only goes so far. | 177 | Googling for solutions only goes so far. |
| 177 | 178 | ||
| 178 | ## Use Redis/Memcached | 179 | ## Use Redis/Memcached |
| 179 | 180 | ||
| 180 | As explained above we are using caching basically for everything. It is the | 181 | As explained above we are using caching basically for everything. It is the |
| 181 | corner stone of our services. At first we were very careful about the quantity | 182 | corner stone of our services. At first we were very careful about the quantity |
| 182 | of things we stored in [Redis](https://redis.io/). But we later found out that | 183 | of things we stored in [Redis](https://redis.io/). But we later found out that |
| 183 | the memory footprint is very low even when storing large amount of data in it. | 184 | the memory footprint is very low even when storing large amount of data in it. |
| 184 | 185 | ||
| 185 | So we gradually increased our usage to caching whole HTML outputs of dashboard. | 186 | So we gradually increased our usage to caching whole HTML outputs of dashboard. |
| 186 | This improved our performance in order of magnitude. And by using native TTL | 187 | This improved our performance in order of magnitude. And by using native TTL |
| 187 | support this goes hand in hand with our needs. | 188 | support this goes hand in hand with our needs. |
| 188 | 189 | ||
| 189 | The reason why we choose [Redis](https://redis.io/) over [Memcached](https://memcached.org/) | 190 | The reason why we choose [Redis](https://redis.io/) over |
| 190 | was the nature of scalability of Redis out of the box. But all this can be | 191 | [Memcached](https://memcached.org/) was the nature of scalability of Redis out |
| 191 | achieved with Memcached. | 192 | of the box. But all this can be achieved with Memcached. |
| 192 | 193 | ||
| 193 | ## Conclusion | 194 | ## Conclusion |
| 194 | 195 | ||
| 195 | There are a lot more details that could have been written and every single | 196 | There are a lot more details that could have been written and every single topic |
| 196 | topic in here deserves it's own post but you probably got the idea about | 197 | in here deserves it's own post but you probably got the idea about the problems |
| 197 | the problems we faced. | 198 | we faced. |
| 198 | |||
diff --git a/content/posts/2017-04-21-profiling-python-web-applications-with-visual-tools.md b/content/posts/2017-04-21-profiling-python-web-applications-with-visual-tools.md index 911e6e0..2e36eaf 100644 --- a/content/posts/2017-04-21-profiling-python-web-applications-with-visual-tools.md +++ b/content/posts/2017-04-21-profiling-python-web-applications-with-visual-tools.md | |||
| @@ -5,10 +5,9 @@ date: 2017-04-21T12:00:00+02:00 | |||
| 5 | draft: false | 5 | draft: false |
| 6 | --- | 6 | --- |
| 7 | 7 | ||
| 8 | I have been profiling my software with KCachegrind for a long time now and I | 8 | I have been profiling my software with KCachegrind for a long time now and I was |
| 9 | was missing this option when I am developing API's or other web services. I | 9 | missing this option when I am developing API's or other web services. I always |
| 10 | always knew that this is possible but never really took the time and dive | 10 | knew that this is possible but never really took the time and dive into it. |
| 11 | into it. | ||
| 12 | 11 | ||
| 13 | Before we begin there are some requirements. We will need to: | 12 | Before we begin there are some requirements. We will need to: |
| 14 | 13 | ||
| @@ -17,7 +16,9 @@ Before we begin there are some requirements. We will need to: | |||
| 17 | - visualize data with [KCachegrind](http://kcachegrind.sourceforge.net/html/Home.html) or [Profiling Viewer](http://www.profilingviewer.com/). | 16 | - visualize data with [KCachegrind](http://kcachegrind.sourceforge.net/html/Home.html) or [Profiling Viewer](http://www.profilingviewer.com/). |
| 18 | 17 | ||
| 19 | 18 | ||
| 20 | If you are using MacOS you should check out [Profiling Viewer](http://www.profilingviewer.com/) or [MacCallGrind](http://www.maccallgrind.com/). | 19 | If you are using MacOS you should check out [Profiling |
| 20 | Viewer](http://www.profilingviewer.com/) or | ||
| 21 | [MacCallGrind](http://www.maccallgrind.com/). | ||
| 21 | 22 | ||
| 22 |  | 23 |  |
| 23 | 24 | ||
| @@ -28,7 +29,7 @@ We will be dividing this post into two main categories: | |||
| 28 | 29 | ||
| 29 | ## Simple web-service | 30 | ## Simple web-service |
| 30 | 31 | ||
| 31 | Let's use virtualenv so we won't pollute our base system. If you don't have | 32 | Let's use virtualenv so we won't pollute our base system. If you don't have |
| 32 | virtualenv installed on your system you can install it with pip command. | 33 | virtualenv installed on your system you can install it with pip command. |
| 33 | 34 | ||
| 34 | ```bash | 35 | ```bash |
| @@ -73,8 +74,8 @@ $ pip install bottle | |||
| 73 | $ deactivate | 74 | $ deactivate |
| 74 | ``` | 75 | ``` |
| 75 | 76 | ||
| 76 | We are now ready to write simple web service. Let's create file app.py and | 77 | We are now ready to write simple web service. Let's create file app.py and paste |
| 77 | paste code bellow in this newly created file. | 78 | code bellow in this newly created file. |
| 78 | 79 | ||
| 79 | ```python | 80 | ```python |
| 80 | # -*- coding: utf-8 -*- | 81 | # -*- coding: utf-8 -*- |
| @@ -126,8 +127,8 @@ if __name__ == '__main__': | |||
| 126 | # open browser 'http://0.0.0.0:4000' | 127 | # open browser 'http://0.0.0.0:4000' |
| 127 | ``` | 128 | ``` |
| 128 | 129 | ||
| 129 | When browser hits awesome\_random\_number() function profile is created in | 130 | When browser hits awesome\_random\_number() function profile is created in prof/ |
| 130 | prof/ subfolder. | 131 | subfolder. |
| 131 | 132 | ||
| 132 | ## Visualize profile | 133 | ## Visualize profile |
| 133 | 134 | ||
| @@ -139,26 +140,27 @@ $ pyprof2calltree -i awesome_random_number.prof | |||
| 139 | # this creates 'awesome_random_number.prof.log' file in the same folder | 140 | # this creates 'awesome_random_number.prof.log' file in the same folder |
| 140 | ``` | 141 | ``` |
| 141 | 142 | ||
| 142 | This file can be opened with visualizing tools listed above. In this case we | 143 | This file can be opened with visualizing tools listed above. In this case we |
| 143 | will be using Profilling Viewer under MacOS. You can open image in new tab. | 144 | will be using Profilling Viewer under MacOS. You can open image in new tab. As |
| 144 | As you can see from this example there is hierarchy of execution order of | 145 | you can see from this example there is hierarchy of execution order of your |
| 145 | your code. | 146 | code. |
| 146 | 147 | ||
| 147 |  | 148 |  |
| 148 | 149 | ||
| 149 | > Make sure you convert output of the cProfile output every time you want to | 150 | > Make sure you convert output of the cProfile output every time you want to |
| 150 | refresh and take a look at your possible optimizations because cProfile | 151 | refresh and take a look at your possible optimizations because cProfile updates |
| 151 | updates .prof file every time browser hits the function. | 152 | .prof file every time browser hits the function. |
| 152 | 153 | ||
| 153 | This is just a simple example but when you are developing real-life applications | 154 | This is just a simple example but when you are developing real-life applications |
| 154 | this can be very illuminating, especially to see which parts of your code are | 155 | this can be very illuminating, especially to see which parts of your code are |
| 155 | bottlenecks and need to be optimized. | 156 | bottlenecks and need to be optimized. |
| 156 | 157 | ||
| 157 | ## Update 2017-04-22 | 158 | ## Update 2017-04-22 |
| 158 | 159 | ||
| 159 | Reddit user [mvt](https://www.reddit.com/user/mvt) also recommended this | 160 | Reddit user [mvt](https://www.reddit.com/user/mvt) also recommended this awesome |
| 160 | awesome web based profile visualizer [SnakeViz](https://jiffyclub.github.io/snakeviz/) | 161 | web based profile visualizer [SnakeViz](https://jiffyclub.github.io/snakeviz/) |
| 161 | that directly takes output from [cProfile](https://docs.python.org/2/library/profile.html#module-cProfile) | 162 | that directly takes output from |
| 163 | [cProfile](https://docs.python.org/2/library/profile.html#module-cProfile) | ||
| 162 | module. | 164 | module. |
| 163 | 165 | ||
| 164 | <div class="reddit-embed" data-embed-media="www.redditmedia.com" data-embed-parent="false" data-embed-live="false" data-embed-uuid="583880c1-002e-41ed-a373-020a0ef2cff9" data-embed-created="2017-04-22T19:46:54.810Z"><a href="https://www.reddit.com/r/Python/comments/66v373/profiling_python_web_applications_with_visual/dgljhsb/">Comment</a> from discussion <a href="https://www.reddit.com/r/Python/comments/66v373/profiling_python_web_applications_with_visual/">Profiling Python web applications with visual tools</a>.</div><script async src="https://www.redditstatic.com/comment-embed.js"></script> | 166 | <div class="reddit-embed" data-embed-media="www.redditmedia.com" data-embed-parent="false" data-embed-live="false" data-embed-uuid="583880c1-002e-41ed-a373-020a0ef2cff9" data-embed-created="2017-04-22T19:46:54.810Z"><a href="https://www.reddit.com/r/Python/comments/66v373/profiling_python_web_applications_with_visual/dgljhsb/">Comment</a> from discussion <a href="https://www.reddit.com/r/Python/comments/66v373/profiling_python_web_applications_with_visual/">Profiling Python web applications with visual tools</a>.</div><script async src="https://www.redditstatic.com/comment-embed.js"></script> |
| @@ -201,4 +203,3 @@ $ pip install snakeviz --user | |||
| 201 | 203 | ||
| 202 | Or as suggested by [mvt](https://www.reddit.com/user/mvt) you can | 204 | Or as suggested by [mvt](https://www.reddit.com/user/mvt) you can |
| 203 | use [pipsi](https://github.com/mitsuhiko/pipsi). | 205 | use [pipsi](https://github.com/mitsuhiko/pipsi). |
| 204 | |||
diff --git a/content/posts/2017-08-11-simple-iot-application.md b/content/posts/2017-08-11-simple-iot-application.md index a0ac4be..e7e086b 100644 --- a/content/posts/2017-08-11-simple-iot-application.md +++ b/content/posts/2017-08-11-simple-iot-application.md | |||
| @@ -7,34 +7,35 @@ draft: false | |||
| 7 | 7 | ||
| 8 | ## Initial thoughts | 8 | ## Initial thoughts |
| 9 | 9 | ||
| 10 | I have been developing these kind of application for the better part of my last | 10 | I have been developing these kind of application for the better part of my last |
| 11 | 5 years and people keep asking me how to approach developing such application | 11 | 5 years and people keep asking me how to approach developing such application |
| 12 | and I will give a try explaining it here. | 12 | and I will give a try explaining it here. |
| 13 | 13 | ||
| 14 | IOT applications are really no different than any other kind of applications. | 14 | IOT applications are really no different than any other kind of applications. |
| 15 | We have data that needs to be collected and visualized in some form of tables | 15 | We have data that needs to be collected and visualized in some form of tables or |
| 16 | or charts. The main difference here is that most of the times these data is | 16 | charts. The main difference here is that most of the times these data is |
| 17 | collected by some kind of device foreign to developer that mainly operates in | 17 | collected by some kind of device foreign to developer that mainly operates in |
| 18 | web domain. But fear not, it's not that different than writing some JavaScript. | 18 | web domain. But fear not, it's not that different than writing some JavaScript. |
| 19 | 19 | ||
| 20 | There are many devices able to transmit data via wireless or wired network by | 20 | There are many devices able to transmit data via wireless or wired network by |
| 21 | default but for the sake of example we will be using commonly known Arduino | 21 | default but for the sake of example we will be using commonly known Arduino with |
| 22 | with wireless module already on the board → [Arduino MKR1000](https://store.arduino.cc/arduino-mkr1000). | 22 | wireless module already on the board → [Arduino |
| 23 | 23 | MKR1000](https://store.arduino.cc/arduino-mkr1000). | |
| 24 | In order to make this little project as accessible to others as possible I will | 24 | |
| 25 | try to make it as inexpensive as possible. And by this I mean that I will avoid | 25 | In order to make this little project as accessible to others as possible I will |
| 26 | using hosted virtual servers and will be using my own laptop as a server. But | 26 | try to make it as inexpensive as possible. And by this I mean that I will avoid |
| 27 | you must buy Arduino MKR1000 to follow steps below. But if you would want to | 27 | using hosted virtual servers and will be using my own laptop as a server. But |
| 28 | deploy this software I would suggest using | 28 | you must buy Arduino MKR1000 to follow steps below. But if you would want to |
| 29 | [DigitalOcean](https://www.digitalocean.com) → smallest VPS is only per month | 29 | deploy this software I would suggest using |
| 30 | making this one of the most affordable option out there. Please notice that | 30 | [DigitalOcean](https://www.digitalocean.com) → smallest VPS is only per month |
| 31 | this software will not run on stock web hosting that only supports LAMP | 31 | making this one of the most affordable option out there. Please notice that this |
| 32 | (Linux, Apache, MySQL, and PHP). | 32 | software will not run on stock web hosting that only supports LAMP (Linux, |
| 33 | 33 | Apache, MySQL, and PHP). | |
| 34 | But before we begin please take notice that this is strictly experimental code | 34 | |
| 35 | and not well optimized and there are much better ways in handling some aspects | 35 | But before we begin please take notice that this is strictly experimental code |
| 36 | of the application but that requires much deeper knowledge of technology that | 36 | and not well optimized and there are much better ways in handling some aspects |
| 37 | is not needed for an example like this. | 37 | of the application but that requires much deeper knowledge of technology that is |
| 38 | not needed for an example like this. | ||
| 38 | 39 | ||
| 39 | **Development steps** | 40 | **Development steps** |
| 40 | 41 | ||
| @@ -42,32 +43,34 @@ is not needed for an example like this. | |||
| 42 | 2. Prototype C++ code that will read "sensor data" and transmit it to API. | 43 | 2. Prototype C++ code that will read "sensor data" and transmit it to API. |
| 43 | 3. Data visualization with charts → extends Python web application. | 44 | 3. Data visualization with charts → extends Python web application. |
| 44 | 45 | ||
| 45 | Step 1. and 3. will share the same web application. One route will be dedicated | 46 | Step 1. and 3. will share the same web application. One route will be dedicated |
| 46 | to API and another to serving HTML with chart. | 47 | to API and another to serving HTML with chart. |
| 47 | 48 | ||
| 48 | Schema below represents what we will try to achieve and how different parts | 49 | Schema below represents what we will try to achieve and how different parts |
| 49 | correlates to each other. | 50 | correlates to each other. |
| 50 | 51 | ||
| 51 |  | 52 |  |
| 52 | 53 | ||
| 53 | ## Simple Python API | 54 | ## Simple Python API |
| 54 | 55 | ||
| 55 | I have always been a fan of simplicity so we will be using [Bottle: Python Web Framework](https://bottlepy.org/docs/dev/). | 56 | I have always been a fan of simplicity so we will be using [Bottle: Python Web |
| 56 | It is a single file web framework that seriously simplifies working with routes, | 57 | Framework](https://bottlepy.org/docs/dev/). It is a single file web framework |
| 57 | templating and has built-in web server that satisfies our need in this case. | 58 | that seriously simplifies working with routes, templating and has built-in web |
| 59 | server that satisfies our need in this case. | ||
| 58 | 60 | ||
| 59 | First we need to install bottle package. This can be done by downloading | 61 | First we need to install bottle package. This can be done by downloading |
| 60 | ```bottle.py``` and placing it in the root of your application or by using | 62 | ```bottle.py``` and placing it in the root of your application or by using pip |
| 61 | pip software ```pip install bottle --user```. | 63 | software ```pip install bottle --user```. |
| 62 | 64 | ||
| 63 | If you are using Linux or MacOS then Python is already installed. If you will | 65 | If you are using Linux or MacOS then Python is already installed. If you will |
| 64 | try to test this on Windows please install [Python for Windows](https://www.python.org/downloads/windows/). | 66 | try to test this on Windows please install [Python for |
| 65 | There may be some problems with path when you will try to launch | 67 | Windows](https://www.python.org/downloads/windows/). There may be some problems |
| 66 | ```python webapp.py``` so please take care of this before you continue. | 68 | with path when you will try to launch ```python webapp.py``` so please take care |
| 69 | of this before you continue. | ||
| 67 | 70 | ||
| 68 | ### Basic web application | 71 | ### Basic web application |
| 69 | 72 | ||
| 70 | Most basic bottle application is quite simple. Paste code below in | 73 | Most basic bottle application is quite simple. Paste code below in |
| 71 | ```webapp.py``` file and save. | 74 | ```webapp.py``` file and save. |
| 72 | 75 | ||
| 73 | ```python | 76 | ```python |
| @@ -96,59 +99,62 @@ if __name__ == "__main__": | |||
| 96 | ) | 99 | ) |
| 97 | ``` | 100 | ``` |
| 98 | 101 | ||
| 99 | To run this simple application you should open command prompt or terminal on | 102 | To run this simple application you should open command prompt or terminal on |
| 100 | your machine and go to the folder containing your file and type | 103 | your machine and go to the folder containing your file and type ```python |
| 101 | ```python webapp.py```. If everything goes ok then open your web browser and | 104 | webapp.py```. If everything goes ok then open your web browser and point it to |
| 102 | point it to ```http://0.0.0.0:5000```. | 105 | ```http://0.0.0.0:5000```. |
| 103 | 106 | ||
| 104 | If you would like change the port of your application (like port 80) and not | 107 | If you would like change the port of your application (like port 80) and not use |
| 105 | use root to run your app this will present a problem. The TCP/IP port numbers | 108 | root to run your app this will present a problem. The TCP/IP port numbers below |
| 106 | below 1024 are privileged ports → this is a security feature. So in order of | 109 | 1024 are privileged ports → this is a security feature. So in order of |
| 107 | simplicity and security use a port number above 1024 like I have used port | 110 | simplicity and security use a port number above 1024 like I have used port 5000. |
| 108 | 5000. | ||
| 109 | 111 | ||
| 110 | If this fails at any time please fix it before you continue, because nothing | 112 | If this fails at any time please fix it before you continue, because nothing |
| 111 | below will work otherwise. | 113 | below will work otherwise. |
| 112 | 114 | ||
| 113 | We use 0.0.0.0 as default host so that this app is available over your local | 115 | We use 0.0.0.0 as default host so that this app is available over your local |
| 114 | network. If you find your local ip ```ifconfig``` and try accessing this site | 116 | network. If you find your local ip ```ifconfig``` and try accessing this site |
| 115 | with your phone (if on same network/router as your machine) this should work | 117 | with your phone (if on same network/router as your machine) this should work as |
| 116 | as well (example of such ip ```http://192.168.1.15:5000```). This is a must | 118 | well (example of such ip ```http://192.168.1.15:5000```). This is a must have |
| 117 | have because Arduino will be accessing this application to send it's data. | 119 | because Arduino will be accessing this application to send it's data. |
| 118 | 120 | ||
| 119 | ### Web application security | 121 | ### Web application security |
| 120 | 122 | ||
| 121 | There is a lot to be said about security and is a topic of many books. Of course | 123 | There is a lot to be said about security and is a topic of many books. Of course |
| 122 | all this can not be written here but to just establish some basic | 124 | all this can not be written here but to just establish some basic security → you |
| 123 | security → you should always use SSL with your application. Some fantastic free | 125 | should always use SSL with your application. Some fantastic free certificates |
| 124 | certificates are available by [Let's Encrypt - Free SSL/TLS Certificates](https://letsencrypt.org). | 126 | are available by [Let's Encrypt - Free SSL/TLS |
| 125 | With SSL certificate installed you should then make use of HTTP headers and | 127 | Certificates](https://letsencrypt.org). With SSL certificate installed you |
| 126 | send your "API key" via a header. If your key is send via header then this | 128 | should then make use of HTTP headers and send your "API key" via a header. If |
| 127 | key is encrypted by SSL and send encrypted over the network. Never send your | 129 | your key is send via header then this key is encrypted by SSL and send encrypted |
| 128 | api keys by GET parameter like ```http://example.com/?api_key=somekeyvalue```. | 130 | over the network. Never send your api keys by GET parameter like |
| 129 | The problem that this kind of sending presents is that this key is visible in | 131 | ```http://example.com/?api_key=somekeyvalue```. The problem that this kind of |
| 130 | logs and by network sniffers. | 132 | sending presents is that this key is visible in logs and by network sniffers. |
| 131 | 133 | ||
| 132 | There is a fantastic article describing some aspects about security: [11 Web Application Security Best Practices](https://www.keycdn.com/blog/web-application-security-best-practices/). Please check it out. | 134 | There is a fantastic article describing some aspects about security: [11 Web |
| 135 | Application Security Best | ||
| 136 | Practices](https://www.keycdn.com/blog/web-application-security-best-practices/). Please | ||
| 137 | check it out. | ||
| 133 | 138 | ||
| 134 | ### Simple API for writing data-points | 139 | ### Simple API for writing data-points |
| 135 | 140 | ||
| 136 | We will now be using boilerplate code from example above and extend it to be | 141 | We will now be using boilerplate code from example above and extend it to be |
| 137 | able to write data received by API to local storage. For example use I will | 142 | SQLite3 because it plays well with Python and can store quite large amount of |
| 138 | use SQLite3 because it plays well with Python and can store quite large amount | 143 | able to write data received by API to local storage. For example use I will use |
| 139 | of data. I have been using it to collect gigabytes of data in a single database | 144 | data. I have been using it to collect gigabytes of data in a single database |
| 140 | without any corruption or problems → your experience may vary. | 145 | without any corruption or problems → your experience may vary. |
| 141 | 146 | ||
| 142 | To avoid learning SQLite I will be using [Dataset: databases for lazy people](https://dataset.readthedocs.io/en/latest/index.html). | 147 | To avoid learning SQLite I will be using [Dataset: databases for lazy |
| 143 | This package abstracts SQL and simplifies writing and reading data from | 148 | people](https://dataset.readthedocs.io/en/latest/index.html). This package |
| 144 | database. You should install this package with pip software | 149 | abstracts SQL and simplifies writing and reading data from database. You should |
| 145 | ```pip install dataset --user```. | 150 | install this package with pip software ```pip install dataset --user```. |
| 146 | 151 | ||
| 147 | Because API will use POST method I will be testing if code works correctly by | 152 | Because API will use POST method I will be testing if code works correctly by |
| 148 | using [Restlet Client for Google Chrome](https://chrome.google.com/webstore/detail/restlet-client-rest-api-t/aejoelaoggembcahagimdiliamlcdmfm). | 153 | using [Restlet Client for Google |
| 154 | Chrome](https://chrome.google.com/webstore/detail/restlet-client-rest-api-t/aejoelaoggembcahagimdiliamlcdmfm). | ||
| 149 | This software also allows you to set headers → for basic security with API_KEY. | 155 | This software also allows you to set headers → for basic security with API_KEY. |
| 150 | 156 | ||
| 151 | To quickly generate passwords or API keys I usually use this nifty website | 157 | To quickly generate passwords or API keys I usually use this nifty website |
| 152 | [RandomKeygen](https://randomkeygen.com/). | 158 | [RandomKeygen](https://randomkeygen.com/). |
| 153 | 159 | ||
| 154 | Copy and paste code below over your previous code in file ```webapp.py```. | 160 | Copy and paste code below over your previous code in file ```webapp.py```. |
| @@ -204,12 +210,12 @@ if __name__ == "__main__": | |||
| 204 | ) | 210 | ) |
| 205 | ``` | 211 | ``` |
| 206 | 212 | ||
| 207 | To run this simply go to folder containing python file and run | 213 | To run this simply go to folder containing python file and run ```python |
| 208 | ```python webapp.py``` from terminal. If everything goes ok you should have | 214 | webapp.py``` from terminal. If everything goes ok you should have simple API |
| 209 | simple API available via POST method on /api route. | 215 | available via POST method on /api route. |
| 210 | 216 | ||
| 211 | After testing the service with Restlet Client you should be able to view | 217 | After testing the service with Restlet Client you should be able to view your |
| 212 | your data in a database file ```data.db```. | 218 | data in a database file ```data.db```. |
| 213 | 219 | ||
| 214 |  | 220 |  |
| 215 | 221 | ||
| @@ -218,38 +224,38 @@ for SQLite → [DB Browser for SQLite](http://sqlitebrowser.org/). | |||
| 218 | 224 | ||
| 219 |  | 225 |  |
| 220 | 226 | ||
| 221 | Table structure is as simple as it can be. We have ts (timestamp) and | 227 | Table structure is as simple as it can be. We have ts (timestamp) and value |
| 222 | value (value from Arduino). As you can see timestamp is generated on API | 228 | (value from Arduino). As you can see timestamp is generated on API side. If you |
| 223 | side. If you would happen to have atomic clock on Arduino it would be then | 229 | would happen to have atomic clock on Arduino it would be then better to generate |
| 224 | better to generate and send timestamp with the value. This would be | 230 | and send timestamp with the value. This would be particularity useful if we |
| 225 | particularity useful if we would be collecting sensor data at a higher | 231 | would be collecting sensor data at a higher frequency and then sending this data |
| 226 | frequency and then sending this data in bulk to API. | 232 | in bulk to API. |
| 227 | 233 | ||
| 228 | If you will deploy this app with uWSGI and multi-threaded, use | 234 | If you will deploy this app with uWSGI and multi-threaded, use DSN (Data Source |
| 229 | DSN (Data Source Name) url with ```?check_same_thread=False```. | 235 | Name) url with ```?check_same_thread=False```. |
| 230 | 236 | ||
| 231 | Ok, now that we have some sort of a working API with some basic security | 237 | Ok, now that we have some sort of a working API with some basic security so |
| 232 | so unwanted people can not post data to your database can we proceed further | 238 | unwanted people can not post data to your database can we proceed further and |
| 233 | and try to program Arduino to send data to API. | 239 | try to program Arduino to send data to API. |
| 234 | 240 | ||
| 235 | ## Sending data to API with Arduino MKR1000 | 241 | ## Sending data to API with Arduino MKR1000 |
| 236 | 242 | ||
| 237 | First of all you should have MKR1000 module and microUSB cable to proceed. | 243 | First of all you should have MKR1000 module and microUSB cable to proceed. If |
| 238 | If you have ever done any work with Arduino you should know that you also | 244 | you have ever done any work with Arduino you should know that you also need |
| 239 | need [Arduino IDE](https://www.arduino.cc/en/Main/Software). On provided link | 245 | [Arduino IDE](https://www.arduino.cc/en/Main/Software). On provided link you |
| 240 | you should be able to download and install IDE. Once that task is completed | 246 | should be able to download and install IDE. Once that task is completed and you |
| 241 | and you have successfully run blink example you should proceed to the next step. | 247 | have successfully run blink example you should proceed to the next step. |
| 242 | 248 | ||
| 243 | In order to use wireless capabilities of MKR1000 you need to first install | 249 | In order to use wireless capabilities of MKR1000 you need to first install |
| 244 | [WiFi101 library](https://www.arduino.cc/en/Reference/WiFi101) in Arduino IDE. | 250 | [WiFi101 library](https://www.arduino.cc/en/Reference/WiFi101) in Arduino IDE. |
| 245 | Please check before you install, you may already have it installed. | 251 | Please check before you install, you may already have it installed. |
| 246 | 252 | ||
| 247 | Code below is a working example that sends data to API. Before you try to test | 253 | Code below is a working example that sends data to API. Before you try to test |
| 248 | your code make sure you have run Python web application. Then change settings | 254 | your code make sure you have run Python web application. Then change settings |
| 249 | for wifi, api endpoint and api_key. If by some reason code bellow doesn't work | 255 | for wifi, api endpoint and api_key. If by some reason code bellow doesn't work |
| 250 | for you please leave a comment and I'll try to help. | 256 | for you please leave a comment and I'll try to help. |
| 251 | 257 | ||
| 252 | Once you have opened IDE and copied this code try to compile and upload it. | 258 | Once you have opened IDE and copied this code try to compile and upload it. |
| 253 | Then open "Serial monitor" to see if any output is presented by Arduino. | 259 | Then open "Serial monitor" to see if any output is presented by Arduino. |
| 254 | 260 | ||
| 255 | ```c | 261 | ```c |
| @@ -335,50 +341,50 @@ void loop() { | |||
| 335 | } | 341 | } |
| 336 | ``` | 342 | ``` |
| 337 | 343 | ||
| 338 | As seen from example you can notice that Arduino is generating random integer | 344 | As seen from example you can notice that Arduino is generating random integer |
| 339 | between [ 0 .. 1000 ]. You can easily replace this with a temperature sensor | 345 | between [ 0 .. 1000 ]. You can easily replace this with a temperature sensor or |
| 340 | or any other kind of sensor. | 346 | any other kind of sensor. |
| 341 | 347 | ||
| 342 | Now that we have API under the hood and Arduino is sending demo data we can | 348 | Now that we have API under the hood and Arduino is sending demo data we can now |
| 343 | now focus on data visualization. | 349 | focus on data visualization. |
| 344 | 350 | ||
| 345 | ## Data visualization | 351 | ## Data visualization |
| 346 | 352 | ||
| 347 | Before we continue we should examine our project folder structure. Currently | 353 | Before we continue we should examine our project folder structure. Currently we |
| 348 | we only have two files in our project: | 354 | only have two files in our project: |
| 349 | 355 | ||
| 350 | _simple-iot-app/_ | 356 | _simple-iot-app/_ |
| 351 | 357 | ||
| 352 | * _webapp.py_ | 358 | * _webapp.py_ |
| 353 | * _data.db_ | 359 | * _data.db_ |
| 354 | 360 | ||
| 355 | We will now add HTML template that will contain CSS and JavaScript code inline | 361 | We will now add HTML template that will contain CSS and JavaScript code inline |
| 356 | for the simplicity reason. And for the bottle framework to be able to scan root | 362 | for the simplicity reason. And for the bottle framework to be able to scan root |
| 357 | application folder for templates we will add | 363 | application folder for templates we will add ```bottle.TEMPLATE_PATH.insert(0, |
| 358 | ```bottle.TEMPLATE_PATH.insert(0, "./")``` in ```webapp.py```. By default bottle | 364 | "./")``` in ```webapp.py```. By default bottle framework uses ```views/``` |
| 359 | framework uses ```views/``` subfolder to store templates. This is not the ideal | 365 | subfolder to store templates. This is not the ideal situation and if you will |
| 360 | situation and if you will use bottle to develop web applications you should use | 366 | use bottle to develop web applications you should use native behavior and store |
| 361 | native behavior and store templates in it's predefined folder. But for the sake | 367 | templates in it's predefined folder. But for the sake of example we will |
| 362 | of example we will over-ride this. Be careful to fully replace your code with | 368 | over-ride this. Be careful to fully replace your code with new code that is |
| 363 | new code that is provided below. Avoid partially replacing code in file :) Also | 369 | provided below. Avoid partially replacing code in file :) Also new code for |
| 364 | new code for reading data-points is provided in Python example below. | 370 | reading data-points is provided in Python example below. |
| 365 | 371 | ||
| 366 | First we add new route to our web application. It should be trigger when browser | 372 | First we add new route to our web application. It should be trigger when browser |
| 367 | hits root of application ```http://0.0.0.0:5000/```. This route will do nothing | 373 | hits root of application ```http://0.0.0.0:5000/```. This route will do nothing |
| 368 | more than render ```frontend.html``` template. This is done by | 374 | more than render ```frontend.html``` template. This is done by ```return |
| 369 | ```return bottle.template("frontend.html")```. Check code below to further | 375 | bottle.template("frontend.html")```. Check code below to further examine how |
| 370 | examine how exactly this is done. | 376 | exactly this is done. |
| 371 | 377 | ||
| 372 | Now we will expand ```/api``` route and use different methods to write or | 378 | Now we will expand ```/api``` route and use different methods to write or read |
| 373 | read data-points. For writing data-point we will use POST method and for | 379 | data-points. For writing data-point we will use POST method and for reading |
| 374 | reading points we will use GET method. GET method will return JSON object | 380 | points we will use GET method. GET method will return JSON object with latest |
| 375 | with latest readings and historical data. | 381 | readings and historical data. |
| 376 | 382 | ||
| 377 | There is a fantastic JavaScript library for plotting time-series charts | 383 | There is a fantastic JavaScript library for plotting time-series charts called |
| 378 | called [MetricsGraphics.js](https://www.metricsgraphicsjs.org) that is | 384 | [MetricsGraphics.js](https://www.metricsgraphicsjs.org) that is based on |
| 379 | based on [D3.js](https://d3js.org/) library for visualizing data. | 385 | [D3.js](https://d3js.org/) library for visualizing data. |
| 380 | 386 | ||
| 381 | Data schema required by MetricsGraphics.js → to achieve this we need to | 387 | Data schema required by MetricsGraphics.js → to achieve this we need to |
| 382 | transform data from database into this format: | 388 | transform data from database into this format: |
| 383 | 389 | ||
| 384 | ```json | 390 | ```json |
| @@ -394,9 +400,9 @@ transform data from database into this format: | |||
| 394 | ] | 400 | ] |
| 395 | ``` | 401 | ``` |
| 396 | 402 | ||
| 397 | Web application is now complete and we only need ```frontend.html``` that we | 403 | Web application is now complete and we only need ```frontend.html``` that we |
| 398 | will develop now. If you would try to start web app now and go to root app | 404 | will develop now. If you would try to start web app now and go to root app this |
| 399 | this will return error because we don't have frontend.html yet. | 405 | will return error because we don't have frontend.html yet. |
| 400 | 406 | ||
| 401 | ```python | 407 | ```python |
| 402 | # -*- coding: utf-8 -*- | 408 | # -*- coding: utf-8 -*- |
| @@ -477,9 +483,9 @@ if __name__ == "__main__": | |||
| 477 | ) | 483 | ) |
| 478 | ``` | 484 | ``` |
| 479 | 485 | ||
| 480 | And now finally we can implement ```frontend.html```. Create file with this | 486 | And now finally we can implement ```frontend.html```. Create file with this name |
| 481 | name and copy code below. When you are done you can start web application. | 487 | and copy code below. When you are done you can start web application. Steps for |
| 482 | Steps for this part are listed below the code. | 488 | this part are listed below the code. |
| 483 | 489 | ||
| 484 | ```html | 490 | ```html |
| 485 | <!DOCTYPE html> | 491 | <!DOCTYPE html> |
| @@ -572,23 +578,24 @@ Ok, lets now start application and start feeding it data. | |||
| 572 | 2. connect Arduino MKR1000 to power source | 578 | 2. connect Arduino MKR1000 to power source |
| 573 | 3. open browser and go to ```http://0.0.0.0:5000``` | 579 | 3. open browser and go to ```http://0.0.0.0:5000``` |
| 574 | 580 | ||
| 575 | If everything goes well you should be seeing new data-points rendered on | 581 | If everything goes well you should be seeing new data-points rendered on chart |
| 576 | chart every 5 seconds. | 582 | every 5 seconds. |
| 577 | 583 | ||
| 578 | If you navigate to ```http://0.0.0.0:5000``` you should see rendered chart | 584 | If you navigate to ```http://0.0.0.0:5000``` you should see rendered chart as |
| 579 | as shown on picture below. | 585 | shown on picture below. |
| 580 | 586 | ||
| 581 |  | 587 |  |
| 582 | 588 | ||
| 583 | Complete application with all the code is available for [download](/assets/iot-application/simple-iot-application.zip). | 589 | Complete application with all the code is available for |
| 590 | [download](/assets/iot-application/simple-iot-application.zip). | ||
| 584 | 591 | ||
| 585 | ## Conclusion | 592 | ## Conclusion |
| 586 | 593 | ||
| 587 | I hope this clarifies some aspects of IOT application development. Of course | 594 | I hope this clarifies some aspects of IOT application development. Of course |
| 588 | this is a minimal example and is far from what can be done in real life with | 595 | this is a minimal example and is far from what can be done in real life with |
| 589 | some further dive into other technologies. | 596 | some further dive into other technologies. |
| 590 | 597 | ||
| 591 | If you would like to continue exploring IOT world here are some interesting | 598 | If you would like to continue exploring IOT world here are some interesting |
| 592 | resources for you to examine: | 599 | resources for you to examine: |
| 593 | 600 | ||
| 594 | * [Reading Sensors with an Arduino](https://www.allaboutcircuits.com/projects/reading-sensors-with-an-arduino/) | 601 | * [Reading Sensors with an Arduino](https://www.allaboutcircuits.com/projects/reading-sensors-with-an-arduino/) |
| @@ -597,4 +604,3 @@ resources for you to examine: | |||
| 597 | * [Internet of Things (IoT) Tutorials](http://www.tutorialspoint.com/internet_of_things/) | 604 | * [Internet of Things (IoT) Tutorials](http://www.tutorialspoint.com/internet_of_things/) |
| 598 | 605 | ||
| 599 | Any comment or additional ideas are welcomed in comments below. | 606 | Any comment or additional ideas are welcomed in comments below. |
| 600 | |||
diff --git a/content/posts/2018-01-16-using-digitalocean-spaces-object-storage-with-fuse.md b/content/posts/2018-01-16-using-digitalocean-spaces-object-storage-with-fuse.md index bfc77ee..3a62594 100644 --- a/content/posts/2018-01-16-using-digitalocean-spaces-object-storage-with-fuse.md +++ b/content/posts/2018-01-16-using-digitalocean-spaces-object-storage-with-fuse.md | |||
| @@ -5,63 +5,67 @@ date: 2018-01-16T12:00:00+02:00 | |||
| 5 | draft: false | 5 | draft: false |
| 6 | --- | 6 | --- |
| 7 | 7 | ||
| 8 | Couple of months ago [DigitalOcean](https://www.digitalocean.com) introduced | 8 | Couple of months ago [DigitalOcean](https://www.digitalocean.com) introduced new |
| 9 | new product called [Spaces](https://blog.digitalocean.com/introducing-spaces-object-storage/) | 9 | product called |
| 10 | which is Object Storage very similar to Amazon's S3. This really peaked my | 10 | [Spaces](https://blog.digitalocean.com/introducing-spaces-object-storage/) which |
| 11 | interest, because this was something I was missing and even the thought of | 11 | is Object Storage very similar to Amazon's S3. This really peaked my interest, |
| 12 | going over the internet for such functionality was in no interest to me. Also | 12 | because this was something I was missing and even the thought of going over the |
| 13 | in fashion with their previous pricing this also is very cheap and pricing | 13 | internet for such functionality was in no interest to me. Also in fashion with |
| 14 | page is a no-brainer compared to AWS or GCE. [Prices are clearly and precisely defined and outlined](https://www.digitalocean.com/pricing/). | 14 | their previous pricing this also is very cheap and pricing page is a no-brainer |
| 15 | You must love them for that :) | 15 | compared to AWS or GCE. [Prices are clearly and precisely defined and |
| 16 | outlined](https://www.digitalocean.com/pricing/). You must love them for that | ||
| 17 | :) | ||
| 16 | 18 | ||
| 17 | ## Initial requirements | 19 | ## Initial requirements |
| 18 | 20 | ||
| 19 | * Is it possible to use them as a mounted drive with FUSE? (tl;dr YES) | 21 | * Is it possible to use them as a mounted drive with FUSE? (tl;dr YES) |
| 20 | * Will the performance degrade over time and over different sizes of objects? | 22 | * Will the performance degrade over time and over different sizes of objects? |
| 21 | (tl;dr NO&YES) | 23 | (tl;dr NO&YES) |
| 22 | * Can storage be mounted on multiple machines at the same time and be writable? | 24 | * Can storage be mounted on multiple machines at the same time and be writable? |
| 23 | (tl;dr YES) | 25 | (tl;dr YES) |
| 24 | 26 | ||
| 25 | > Let me be clear. This scripts I use are made just for benchmarking and are | 27 | > Let me be clear. This scripts I use are made just for benchmarking and are not |
| 26 | > not intended to be used in real-life situations. Besides that, I am looking | 28 | > intended to be used in real-life situations. Besides that, I am looking into |
| 27 | > into using this approaches but adding caching service in front of it and then | 29 | > using this approaches but adding caching service in front of it and then |
| 28 | > dumping everything as an object to storage. This could potentially be some | 30 | > dumping everything as an object to storage. This could potentially be some |
| 29 | > interesting post of itself. But in case you would need real-time data without | 31 | > interesting post of itself. But in case you would need real-time data without |
| 30 | > eventual consistency please take this scripts as they are: not usable in such | 32 | > eventual consistency please take this scripts as they are: not usable in such |
| 31 | > situations. | 33 | > situations. |
| 32 | 34 | ||
| 33 | ## Is it possible to use them as a mounted drive with FUSE? | 35 | ## Is it possible to use them as a mounted drive with FUSE? |
| 34 | 36 | ||
| 35 | Well, actually they can be used in such manor. Because they are similar to | 37 | Well, actually they can be used in such manor. Because they are similar to [AWS |
| 36 | [AWS S3](https://aws.amazon.com/s3/) many tools are available and you can find | 38 | S3](https://aws.amazon.com/s3/) many tools are available and you can find many |
| 37 | many articles and [Stackoverflow items](https://stackoverflow.com/search?q=s3+fuse). | 39 | articles and [Stackoverflow items](https://stackoverflow.com/search?q=s3+fuse). |
| 38 | 40 | ||
| 39 | To make this work you will need DigitalOcean account. If you don't have one you | 41 | To make this work you will need DigitalOcean account. If you don't have one you |
| 40 | will not be able to test this code. But if you have an account then you go and | 42 | will not be able to test this code. But if you have an account then you go and |
| 41 | [create new Droplet](https://cloud.digitalocean.com/droplets/new?size=s-1vcpu-1gb®ion=ams3&distro=debian&distroImage=debian-9-x64&options=private_networking,install_agent). | 43 | [create new |
| 42 | If you click on this link you will already have preselected Debian 9 with | 44 | Droplet](https://cloud.digitalocean.com/droplets/new?size=s-1vcpu-1gb®ion=ams3&distro=debian&distroImage=debian-9-x64&options=private_networking,install_agent). |
| 45 | If you click on this link you will already have preselected Debian 9 with | ||
| 43 | smallest VM option. | 46 | smallest VM option. |
| 44 | 47 | ||
| 45 | * Please be sure to add you SSH key, because we will login to this machine | 48 | * Please be sure to add you SSH key, because we will login to this machine |
| 46 | remotely. | 49 | remotely. |
| 47 | * If you change your region please remember which one you choose because we | 50 | * If you change your region please remember which one you choose because we will |
| 48 | will need this information when we try to mount space to our machine. | 51 | need this information when we try to mount space to our machine. |
| 49 | 52 | ||
| 50 | Instuctions on how to use SSH keys and how to setup them are available in article | 53 | Instuctions on how to use SSH keys and how to setup them are available in |
| 51 | [How To Use SSH Keys with DigitalOcean Droplets](https://www.digitalocean.com/community/tutorials/how-to-use-ssh-keys-with-digitalocean-droplets). | 54 | article [How To Use SSH Keys with DigitalOcean |
| 55 | Droplets](https://www.digitalocean.com/community/tutorials/how-to-use-ssh-keys-with-digitalocean-droplets). | ||
| 52 | 56 | ||
| 53 |  | 57 |  |
| 54 | 58 | ||
| 55 | After we created Droplet it's time to create new Space. This is done by clicking | 59 | After we created Droplet it's time to create new Space. This is done by clicking |
| 56 | on a button [Create](https://cloud.digitalocean.com/spaces/new) (right top | 60 | on a button [Create](https://cloud.digitalocean.com/spaces/new) (right top |
| 57 | corner) and selecting Spaces. Choose pronounceable ```Unique name``` because we | 61 | corner) and selecting Spaces. Choose pronounceable ```Unique name``` because we |
| 58 | will use it in examples below. You can either choose Private or Public, it | 62 | will use it in examples below. You can either choose Private or Public, it |
| 59 | doesn't matter in our case. And you can always change that in the future. | 63 | doesn't matter in our case. And you can always change that in the future. |
| 60 | 64 | ||
| 61 | When you have created new Space we should [generate Access key](https://cloud.digitalocean.com/settings/api/tokens). | 65 | When you have created new Space we should [generate Access |
| 62 | This link will guide to the page when you can generate this key. After you | 66 | key](https://cloud.digitalocean.com/settings/api/tokens). This link will guide |
| 63 | create new one, please save provided Key and Secret because Secret will not | 67 | to the page when you can generate this key. After you create new one, please |
| 64 | be shown again. | 68 | save provided Key and Secret because Secret will not be shown again. |
| 65 | 69 | ||
| 66 |  | 70 |  |
| 67 | 71 | ||
| @@ -90,14 +94,13 @@ s3fs UNIQUE-NAME /mnt/ -ourl=https://ams3.digitaloceanspaces.com -ouse_cache=/tm | |||
| 90 | echo "Hello cruel world" > /mnt/hello.txt | 94 | echo "Hello cruel world" > /mnt/hello.txt |
| 91 | ``` | 95 | ``` |
| 92 | 96 | ||
| 93 | After all this you can return to your browser and go to | 97 | After all this you can return to your browser and go to [DigitalOcean |
| 94 | [DigitalOcean Spaces](https://cloud.digitalocean.com/spaces) and click on your | 98 | Spaces](https://cloud.digitalocean.com/spaces) and click on your created |
| 95 | created space. If file hello.txt is present you have successfully mounted | 99 | space. If file hello.txt is present you have successfully mounted space to your |
| 96 | space to your machine and wrote data to it. | 100 | machine and wrote data to it. |
| 97 | 101 | ||
| 98 | I choose the same region for my Droplet and my Space but you don't have to. | 102 | I choose the same region for my Droplet and my Space but you don't have to. You |
| 99 | You can have different regions. What this actually does to performance I | 103 | can have different regions. What this actually does to performance I don't know. |
| 100 | don't know. | ||
| 101 | 104 | ||
| 102 | Additional information on FUSE: | 105 | Additional information on FUSE: |
| 103 | 106 | ||
| @@ -106,9 +109,9 @@ Additional information on FUSE: | |||
| 106 | 109 | ||
| 107 | ## Will the performance degrade over time and over different sizes of objects? | 110 | ## Will the performance degrade over time and over different sizes of objects? |
| 108 | 111 | ||
| 109 | For this task I didn't want to just read and write text files or uploading | 112 | For this task I didn't want to just read and write text files or uploading |
| 110 | images. I actually wanted to figure out if using something like SQlite is | 113 | images. I actually wanted to figure out if using something like SQlite is viable |
| 111 | viable in this case. | 114 | in this case. |
| 112 | 115 | ||
| 113 | ### Measurement experiment 1: File copy | 116 | ### Measurement experiment 1: File copy |
| 114 | 117 | ||
| @@ -134,12 +137,12 @@ n=0; while (( n++ < 100 )); do (time cp 1MB.dat /mnt/1MB.$n.dat) |& tee -a 1MB.r | |||
| 134 | n=0; while (( n++ < 100 )); do (time cp 10MB.dat /mnt/10MB.$n.dat) |& tee -a 10MB.results.txt; done | 137 | n=0; while (( n++ < 100 )); do (time cp 10MB.dat /mnt/10MB.$n.dat) |& tee -a 10MB.results.txt; done |
| 135 | ``` | 138 | ``` |
| 136 | 139 | ||
| 137 | Files of size 100MB were not successfully transferred and ended up displaying | 140 | Files of size 100MB were not successfully transferred and ended up displaying |
| 138 | error (cp: failed to close '/mnt/100MB.1.dat': Operation not permitted). | 141 | error (cp: failed to close '/mnt/100MB.1.dat': Operation not permitted). |
| 139 | 142 | ||
| 140 | As I suspected, object size is not really that important. Sadly I don't have | 143 | As I suspected, object size is not really that important. Sadly I don't have the |
| 141 | the time to test performance over periods of time. But if some of you would do | 144 | time to test performance over periods of time. But if some of you would do it |
| 142 | it please send me your data. I would be interested in seeing results. | 145 | please send me your data. I would be interested in seeing results. |
| 143 | 146 | ||
| 144 | **Here are plotted results** | 147 | **Here are plotted results** |
| 145 | 148 | ||
| @@ -177,18 +180,18 @@ Measurements are in seconds. | |||
| 177 | })(); | 180 | })(); |
| 178 | </script> | 181 | </script> |
| 179 | 182 | ||
| 180 | As far as these tests show, performance is quite stable and can be predicted | 183 | As far as these tests show, performance is quite stable and can be predicted |
| 181 | which is fantastic. But this is a small test and spans only over couple of | 184 | which is fantastic. But this is a small test and spans only over couple of |
| 182 | hours. So you should not completely trust them. | 185 | hours. So you should not completely trust them. |
| 183 | 186 | ||
| 184 | ### Measurement experiment 2: SQLite performanse | 187 | ### Measurement experiment 2: SQLite performanse |
| 185 | 188 | ||
| 186 | I was unable to use database file directly from mounted drive so this is a | 189 | I was unable to use database file directly from mounted drive so this is a no-go |
| 187 | no-go as I suspected. So I executed code below on a local disk just to get | 190 | as I suspected. So I executed code below on a local disk just to get some |
| 188 | some benchmarks. I inserted 1000 records with DROPTABLE, CREATETABLE, | 191 | benchmarks. I inserted 1000 records with DROPTABLE, CREATETABLE, INSERTMANY, |
| 189 | INSERTMANY, FETCHALL, COMMIT for 1000 times to generate statistics. As you can | 192 | FETCHALL, COMMIT for 1000 times to generate statistics. As you can see |
| 190 | see performance of SQLite is quite amazing. You could then potentially just | 193 | performance of SQLite is quite amazing. You could then potentially just copy |
| 191 | copy file to mounted drive and be done with it. | 194 | file to mounted drive and be done with it. |
| 192 | 195 | ||
| 193 | ```python | 196 | ```python |
| 194 | import time | 197 | import time |
| @@ -305,24 +308,23 @@ and check locking etc. | |||
| 305 | 308 | ||
| 306 | ## Can storage be mounted on multiple machines at the same time and be writable? | 309 | ## Can storage be mounted on multiple machines at the same time and be writable? |
| 307 | 310 | ||
| 308 | Well, this one didn't take long to test. And the answer is **YES**. I mounted | 311 | Well, this one didn't take long to test. And the answer is **YES**. I mounted |
| 309 | space on both machines and measured same performance on both machines. But | 312 | space on both machines and measured same performance on both machines. But |
| 310 | because file is downloaded before write and then uploaded on complete there | 313 | because file is downloaded before write and then uploaded on complete there |
| 311 | could potentially be problems is another process is trying to access the same | 314 | could potentially be problems is another process is trying to access the same |
| 312 | file. | 315 | file. |
| 313 | 316 | ||
| 314 | ## Observations and conslusion | 317 | ## Observations and conslusion |
| 315 | 318 | ||
| 316 | Using Spaces in this way makes it easier to access and manage files. But | 319 | Using Spaces in this way makes it easier to access and manage files. But besides |
| 317 | besides that you would need to write additional code to make this one play | 320 | that you would need to write additional code to make this one play nice with you |
| 318 | nice with you applications. | 321 | applications. |
| 319 | 322 | ||
| 320 | Nevertheless, this was extremely simple to setup and use and this is just | 323 | Nevertheless, this was extremely simple to setup and use and this is just |
| 321 | another excellent product in DigitalOcean product line. I found this exercise | 324 | another excellent product in DigitalOcean product line. I found this exercise |
| 322 | very valuable and am thinking about implementing some sort of mechanism for | 325 | very valuable and am thinking about implementing some sort of mechanism for |
| 323 | SQLite, so data can be stored on Spaces and accessed by many VM's. For a | 326 | SQLite, so data can be stored on Spaces and accessed by many VM's. For a project |
| 324 | project where data doesn't need to be accessible in real-time and can have | 327 | where data doesn't need to be accessible in real-time and can have couple of |
| 325 | couple of minutes old data this would be very interesting. If any of you find | 328 | minutes old data this would be very interesting. If any of you find this |
| 326 | this proposal interesting please write in a comment box below or shoot me an | 329 | proposal interesting please write in a comment box below or shoot me an email |
| 327 | email and I will keep you posted. | 330 | and I will keep you posted. |
| 328 | |||
diff --git a/content/posts/2019-01-03-encoding-binary-data-into-dna-sequence.md b/content/posts/2019-01-03-encoding-binary-data-into-dna-sequence.md index a57201f..f0343ae 100644 --- a/content/posts/2019-01-03-encoding-binary-data-into-dna-sequence.md +++ b/content/posts/2019-01-03-encoding-binary-data-into-dna-sequence.md | |||
| @@ -7,64 +7,59 @@ draft: false | |||
| 7 | 7 | ||
| 8 | ## Initial thoughts | 8 | ## Initial thoughts |
| 9 | 9 | ||
| 10 | Imagine a world where you could go outside and take a leaf from a tree and put | 10 | Imagine a world where you could go outside and take a leaf from a tree and put |
| 11 | it through your personal DNA sequencer and get data like music, videos or | 11 | it through your personal DNA sequencer and get data like music, videos or |
| 12 | computer programs from it. Well, this is all possible now. It was not done | 12 | computer programs from it. Well, this is all possible now. It was not done on a |
| 13 | on a large scale because it is quite expensive to create DNA strands but it's | 13 | large scale because it is quite expensive to create DNA strands but it's |
| 14 | possible. | 14 | possible. |
| 15 | 15 | ||
| 16 | Encoding data into DNA sequence is relatively simple process once you understand | 16 | Encoding data into DNA sequence is relatively simple process once you understand |
| 17 | the relationship between binary data and nucleotides and scientists have been | 17 | the relationship between binary data and nucleotides and scientists have been |
| 18 | making large leaps in this field in order to provide viable long-term storage | 18 | making large leaps in this field in order to provide viable long-term storage |
| 19 | solution for our data that would potentially survive our specie if case of | 19 | solution for our data that would potentially survive our specie if case of |
| 20 | global disaster. We could imprint all the world's knowledge into plants and | 20 | global disaster. We could imprint all the world's knowledge into plants and |
| 21 | ensure the survival of our knowledge. | 21 | ensure the survival of our knowledge. |
| 22 | 22 | ||
| 23 | More optimistic usage for this technology would be easier storage of ever | 23 | More optimistic usage for this technology would be easier storage of ever |
| 24 | growing data we produce every day. Once machines for sequencing DNA become fast | 24 | growing data we produce every day. Once machines for sequencing DNA become fast |
| 25 | enough and cheaper this could mean the next evolution of storing data and | 25 | enough and cheaper this could mean the next evolution of storing data and |
| 26 | abandoning classical hard and solid state drives in data warehouses. | 26 | abandoning classical hard and solid state drives in data warehouses. |
| 27 | 27 | ||
| 28 | As we currently stand this is still not viable but it is quite an amazing and | 28 | As we currently stand this is still not viable but it is quite an amazing and |
| 29 | cool technology. | 29 | cool technology. |
| 30 | 30 | ||
| 31 | My interests in this field are purely in encoding processes and experimental | 31 | My interests in this field are purely in encoding processes and experimental |
| 32 | testing mainly because I don't have the access to this expensive machines. My | 32 | testing mainly because I don't have the access to this expensive machines. My |
| 33 | initial goal was to create a toolkit that can be used by everybody to encode | 33 | initial goal was to create a toolkit that can be used by everybody to encode |
| 34 | their data into a proper DNA sequence. | 34 | their data into a proper DNA sequence. |
| 35 | 35 | ||
| 36 | ## Glossary | 36 | ## Glossary |
| 37 | 37 | ||
| 38 | **deoxyribose** | 38 | **deoxyribose** A five-carbon sugar molecule with a hydrogen atom rather than a |
| 39 | A five-carbon sugar molecule with a hydrogen atom rather than a hydroxyl group | 39 | hydroxyl group in the 2′ position; the sugar component of DNA nucleotides. |
| 40 | in the 2′ position; the sugar component of DNA nucleotides. | ||
| 41 | 40 | ||
| 42 | **double helix** | 41 | **double helix** The molecular shape of DNA in which two strands of nucleotides |
| 43 | The molecular shape of DNA in which two strands of nucleotides wind around | 42 | wind around each other in a spiral shape. |
| 44 | each other in a spiral shape. | ||
| 45 | 43 | ||
| 46 | **nitrogenous base** | 44 | **nitrogenous base** A nitrogen-containing molecule that acts as a base; often |
| 47 | A nitrogen-containing molecule that acts as a base; often referring to one of | 45 | referring to one of the purine or pyrimidine components of nucleic acids. |
| 48 | the purine or pyrimidine components of nucleic acids. | ||
| 49 | 46 | ||
| 50 | **phosphate group** | 47 | **phosphate group** A molecular group consisting of a central phosphorus atom |
| 51 | A molecular group consisting of a central phosphorus atom bound to four oxygen | 48 | bound to four oxygen atoms. |
| 52 | atoms. | ||
| 53 | 49 | ||
| 54 | **RGB** | 50 | **RGB** The RGB color model is an additive color model in which red, green and |
| 55 | The RGB color model is an additive color model in which red, green and blue | 51 | blue light are added together in various ways to reproduce a broad array of |
| 56 | light are added together in various ways to reproduce a broad array of colors. | 52 | colors. |
| 57 | 53 | ||
| 58 | **GCC** | 54 | **GCC** The GNU Compiler Collection is a compiler system produced by the GNU |
| 59 | The GNU Compiler Collection is a compiler system produced by the GNU Project | 55 | Project supporting various programming languages. |
| 60 | supporting various programming languages. | ||
| 61 | 56 | ||
| 62 | ## Data encoding | 57 | ## Data encoding |
| 63 | 58 | ||
| 64 | **TL;DR:** Encoding involves the use of a code to change original data into a | 59 | **TL;DR:** Encoding involves the use of a code to change original data into a |
| 65 | form that can be used by an external process. | 60 | form that can be used by an external process. |
| 66 | 61 | ||
| 67 | Encoding is the process of converting data into a format required for a number | 62 | Encoding is the process of converting data into a format required for a number |
| 68 | of information processing needs, including: | 63 | of information processing needs, including: |
| 69 | 64 | ||
| 70 | - Program compiling and execution | 65 | - Program compiling and execution |
| @@ -74,7 +69,7 @@ of information processing needs, including: | |||
| 74 | Encoding can have two meanings: | 69 | Encoding can have two meanings: |
| 75 | 70 | ||
| 76 | - In computer technology, encoding is the process of applying a specific code, | 71 | - In computer technology, encoding is the process of applying a specific code, |
| 77 | such as letters, symbols and numbers, to data for conversion into an | 72 | such as letters, symbols and numbers, to data for conversion into an |
| 78 | equivalent cipher. | 73 | equivalent cipher. |
| 79 | - In electronics, encoding refers to analog to digital conversion. | 74 | - In electronics, encoding refers to analog to digital conversion. |
| 80 | 75 | ||
| @@ -99,23 +94,25 @@ Encoding can have two meanings: | |||
| 99 | 94 | ||
| 100 | ## What is DNA? | 95 | ## What is DNA? |
| 101 | 96 | ||
| 102 | Deoxyribonucleic acid, a self-replicating material which is | 97 | Deoxyribonucleic acid, a self-replicating material which is **present in nearly |
| 103 | **present in nearly all living organisms** as the main constituent of | 98 | all living organisms** as the main constituent of chromosomes. It is the |
| 104 | chromosomes. It is the **carrier of genetic information**. | 99 | **carrier of genetic information**. |
| 105 | 100 | ||
| 106 | > The nitrogen in our DNA, the calcium in our teeth, the iron in our blood, | 101 | > The nitrogen in our DNA, the calcium in our teeth, the iron in our blood, |
| 107 | > the carbon in our apple pies were made in the interiors of collapsing stars. | 102 | > the carbon in our apple pies were made in the interiors of collapsing stars. |
| 108 | > We are made of starstuff. | 103 | > We are made of starstuff. |
| 109 | > **-- Carl Sagan, Cosmos** | 104 | > **-- Carl Sagan, Cosmos** |
| 110 | 105 | ||
| 111 | The nucleotide in DNA consists of a sugar (deoxyribose), one of four bases | 106 | The nucleotide in DNA consists of a sugar (deoxyribose), one of four bases |
| 112 | (cytosine (C), thymine (T), adenine (A), guanine (G)), and a phosphate. | 107 | (cytosine (C), thymine (T), adenine (A), guanine (G)), and a phosphate. |
| 113 | Cytosine and thymine are pyrimidine bases, while adenine and guanine are purine | 108 | Cytosine and thymine are pyrimidine bases, while adenine and guanine are purine |
| 114 | bases. The sugar and the base together are called a nucleoside. | 109 | bases. The sugar and the base together are called a nucleoside. |
| 115 | 110 | ||
| 116 |  | 111 |  |
| 117 | 112 | ||
| 118 | *DNA (a) forms a double stranded helix, and (b) adenine pairs with thymine and cytosine pairs with guanine. (credit a: modification of work by Jerome Walker, Dennis Myts)* | 113 | *DNA (a) forms a double stranded helix, and (b) adenine pairs with thymine and |
| 114 | cytosine pairs with guanine. (credit a: modification of work by Jerome Walker, | ||
| 115 | Dennis Myts)* | ||
| 119 | 116 | ||
| 120 | ## Encode binary data into DNA sequence | 117 | ## Encode binary data into DNA sequence |
| 121 | 118 | ||
| @@ -128,18 +125,18 @@ As an input file you can use any file you want: | |||
| 128 | - Database files, | 125 | - Database files, |
| 129 | - etc. | 126 | - etc. |
| 130 | 127 | ||
| 131 | Note: If you would copy all the bytes from RAM to file or pipe data to file you | 128 | Note: If you would copy all the bytes from RAM to file or pipe data to file you |
| 132 | could encode also this data as long as you provide file pointer to the encoder. | 129 | could encode also this data as long as you provide file pointer to the encoder. |
| 133 | 130 | ||
| 134 | ### Basic Encoding | 131 | ### Basic Encoding |
| 135 | 132 | ||
| 136 | As already mentioned, the Basic Encoding is based on a simple mapping. Since | 133 | As already mentioned, the Basic Encoding is based on a simple mapping. Since DNA |
| 137 | DNA is composed of 4 nucleotides (Adenine, Cytosine, Guanine, Thymine; usually | 134 | is composed of 4 nucleotides (Adenine, Cytosine, Guanine, Thymine; usually |
| 138 | referred using the first letter). Using this technique we can encode | 135 | referred using the first letter). Using this technique we can encode |
| 139 | 136 | ||
| 140 | $$ log_2(4) = log_2(2^2) = 2 bits $$ | 137 | $$ log_2(4) = log_2(2^2) = 2 bits $$ |
| 141 | 138 | ||
| 142 | using a single nucleotide. In this way, we are able to use the 4 bases that | 139 | using a single nucleotide. In this way, we are able to use the 4 bases that |
| 143 | compose the DNA strand to encode each byte of data. | 140 | compose the DNA strand to encode each byte of data. |
| 144 | 141 | ||
| 145 | | Two bits | Nucleotides | | 142 | | Two bits | Nucleotides | |
| @@ -149,8 +146,8 @@ compose the DNA strand to encode each byte of data. | |||
| 149 | | 01 | **C** (Cytosine) | | 146 | | 01 | **C** (Cytosine) | |
| 150 | | 11 | **T** (Thymine) | | 147 | | 11 | **T** (Thymine) | |
| 151 | 148 | ||
| 152 | With this in mind we can simply encode any data by using two-bit to | 149 | With this in mind we can simply encode any data by using two-bit to Nucleotides |
| 153 | Nucleotides conversion. | 150 | conversion. |
| 154 | 151 | ||
| 155 | ```python | 152 | ```python |
| 156 | { Algorithm 1: Naive byte array to DNA encode } | 153 | { Algorithm 1: Naive byte array to DNA encode } |
| @@ -173,29 +170,29 @@ begin | |||
| 173 | end | 170 | end |
| 174 | ``` | 171 | ``` |
| 175 | 172 | ||
| 176 | Another encoding would be **Goldman encoding**. Using this encoding helps with | 173 | Another encoding would be **Goldman encoding**. Using this encoding helps with |
| 177 | Nonsense mutation (amino acids replaced by a stop codon) that occurs and is | 174 | Nonsense mutation (amino acids replaced by a stop codon) that occurs and is the |
| 178 | the most problematic during translation because it leads to truncated amino | 175 | most problematic during translation because it leads to truncated amino acid |
| 179 | acid sequences, which in turn results in truncated proteins. | 176 | sequences, which in turn results in truncated proteins. |
| 180 | 177 | ||
| 181 | [Where to store big data? In DNA: Nick Goldman at TEDxPrague](https://www.youtube.com/watch?v=a4PiGWNsIEU) | 178 | [Where to store big data? In DNA: Nick Goldman at TEDxPrague](https://www.youtube.com/watch?v=a4PiGWNsIEU) |
| 182 | 179 | ||
| 183 | ### FASTA file format | 180 | ### FASTA file format |
| 184 | 181 | ||
| 185 | In bioinformatics, FASTA format is a text-based format for representing either | 182 | In bioinformatics, FASTA format is a text-based format for representing either |
| 186 | nucleotide sequences or peptide sequences, in which nucleotides or amino acids | 183 | nucleotide sequences or peptide sequences, in which nucleotides or amino acids |
| 187 | are represented using single-letter codes. The format also allows for sequence | 184 | are represented using single-letter codes. The format also allows for sequence |
| 188 | names and comments to precede the sequences. The format originates from the | 185 | names and comments to precede the sequences. The format originates from the |
| 189 | FASTA software package, but has now become a standard in the field of | 186 | FASTA software package, but has now become a standard in the field of |
| 190 | bioinformatics. | 187 | bioinformatics. |
| 191 | 188 | ||
| 192 | The first line in a FASTA file started either with a ">" (greater-than) symbol | 189 | The first line in a FASTA file started either with a ">" (greater-than) symbol |
| 193 | or, less frequently, a ";" (semicolon) was taken as a comment. Subsequent | 190 | or, less frequently, a ";" (semicolon) was taken as a comment. Subsequent lines |
| 194 | lines starting with a semicolon would be ignored by software. Since the only | 191 | starting with a semicolon would be ignored by software. Since the only comment |
| 195 | comment used was the first, it quickly became used to hold a summary | 192 | used was the first, it quickly became used to hold a summary description of the |
| 196 | description of the sequence, often starting with a unique library accession | 193 | sequence, often starting with a unique library accession number, and with time |
| 197 | number, and with time it has become commonplace to always use ">" for the first | 194 | it has become commonplace to always use ">" for the first line and to not use |
| 198 | line and to not use ";" comments (which would otherwise be ignored). | 195 | ";" comments (which would otherwise be ignored). |
| 199 | 196 | ||
| 200 | ``` | 197 | ``` |
| 201 | ;LCBO - Prolactin precursor - Bovine | 198 | ;LCBO - Prolactin precursor - Bovine |
| @@ -218,7 +215,7 @@ GLMPFLHTSKHRSMMLRPLSQALFWTLTMDLLTLTWIGSQPVEYPYTIIGQMASILYFSIILAFLPIAGX | |||
| 218 | IENY | 215 | IENY |
| 219 | ``` | 216 | ``` |
| 220 | 217 | ||
| 221 | FASTA format was extended by [FASTQ](https://en.wikipedia.org/wiki/FASTQ_format) | 218 | FASTA format was extended by [FASTQ](https://en.wikipedia.org/wiki/FASTQ_format) |
| 222 | format from the [Sanger Centre](https://www.sanger.ac.uk/) in Cambridge. | 219 | format from the [Sanger Centre](https://www.sanger.ac.uk/) in Cambridge. |
| 223 | 220 | ||
| 224 | ### PNG encoded DNA sequence | 221 | ### PNG encoded DNA sequence |
| @@ -230,7 +227,7 @@ format from the [Sanger Centre](https://www.sanger.ac.uk/) in Cambridge. | |||
| 230 | | C ➞ Cytosine | (255,0,0) | Red | | 227 | | C ➞ Cytosine | (255,0,0) | Red | |
| 231 | | T ➞ Thymine | (255,255,0) | Yellow | | 228 | | T ➞ Thymine | (255,255,0) | Yellow | |
| 232 | 229 | ||
| 233 | With this in mind we can create a simple algorithm to create PNG representation | 230 | With this in mind we can create a simple algorithm to create PNG representation |
| 234 | of a DNA sequence. | 231 | of a DNA sequence. |
| 235 | 232 | ||
| 236 | ```python | 233 | ```python |
| @@ -252,7 +249,7 @@ end | |||
| 252 | 249 | ||
| 253 | ## Encoding text file in practice | 250 | ## Encoding text file in practice |
| 254 | 251 | ||
| 255 | In this example we will take a simple text file as our input stream for | 252 | In this example we will take a simple text file as our input stream for |
| 256 | encoding. This file will have a quote from Niels Bohr and saved as txt file. | 253 | encoding. This file will have a quote from Niels Bohr and saved as txt file. |
| 257 | 254 | ||
| 258 | > How wonderful that we have met with a paradox. Now we have some hope of | 255 | > How wonderful that we have met with a paradox. Now we have some hope of |
| @@ -306,8 +303,9 @@ After encoding into PNG format this file looks like this. | |||
| 306 | 303 | ||
| 307 | The larger the input stream is the larger the PNG file would be. | 304 | The larger the input stream is the larger the PNG file would be. |
| 308 | 305 | ||
| 309 | Compiled basic Hello World C program with [GCC](https://www.gnu.org/software/gcc/) | 306 | Compiled basic Hello World C program with |
| 310 | would [look like](/assets/dna-sequence/sample.png). | 307 | [GCC](https://www.gnu.org/software/gcc/) would [look |
| 308 | like](/assets/dna-sequence/sample.png). | ||
| 311 | 309 | ||
| 312 | ```c | 310 | ```c |
| 313 | // gcc -O3 -o sample sample.c | 311 | // gcc -O3 -o sample sample.c |
| @@ -370,7 +368,7 @@ First we generate some binary sample data with dd. | |||
| 370 | dd if=<(openssl enc -aes-256-ctr -pass pass:"$(dd if=/dev/urandom bs=128 count=1 2>/dev/null | base64)" -nosalt < /dev/zero) of=1KB.bin bs=1KB count=1 iflag=fullblock | 368 | dd if=<(openssl enc -aes-256-ctr -pass pass:"$(dd if=/dev/urandom bs=128 count=1 2>/dev/null | base64)" -nosalt < /dev/zero) of=1KB.bin bs=1KB count=1 iflag=fullblock |
| 371 | ``` | 369 | ``` |
| 372 | 370 | ||
| 373 | Our freshly generated 1KB file looks something like this (its full of garbage | 371 | Our freshly generated 1KB file looks something like this (its full of garbage |
| 374 | data as intended). | 372 | data as intended). |
| 375 | 373 | ||
| 376 |  | 374 |  |
| @@ -410,4 +408,3 @@ gzip -9 < 10MB.fa > 10MB.fa.gz | |||
| 410 | - https://opentextbc.ca/biology/chapter/9-1-the-structure-of-dna/ | 408 | - https://opentextbc.ca/biology/chapter/9-1-the-structure-of-dna/ |
| 411 | - https://arxiv.org/abs/1801.04774 | 409 | - https://arxiv.org/abs/1801.04774 |
| 412 | - https://en.wikipedia.org/wiki/FASTA_format | 410 | - https://en.wikipedia.org/wiki/FASTA_format |
| 413 | |||
diff --git a/content/posts/2019-10-14-simplifying-and-reducing-clutter.md b/content/posts/2019-10-14-simplifying-and-reducing-clutter.md index 13f4f42..97ddb34 100644 --- a/content/posts/2019-10-14-simplifying-and-reducing-clutter.md +++ b/content/posts/2019-10-14-simplifying-and-reducing-clutter.md | |||
| @@ -5,53 +5,54 @@ date: 2019-10-14T12:00:00+02:00 | |||
| 5 | draft: false | 5 | draft: false |
| 6 | --- | 6 | --- |
| 7 | 7 | ||
| 8 | I recently moved my main working machine back from Hachintosh to Linux. Well | 8 | I recently moved my main working machine back from Hachintosh to Linux. Well the |
| 9 | the experiment was interesting and I have done some great work on macOS but it | 9 | experiment was interesting and I have done some great work on macOS but it was |
| 10 | was time to move back. | 10 | time to move back. |
| 11 | 11 | ||
| 12 | I actually really missed Linux. The simplicity of `apt-get` or just the amount | 12 | I actually really missed Linux. The simplicity of `apt-get` or just the amount |
| 13 | of software that exists for Linux should be a no-brainer. I spent most of my | 13 | of software that exists for Linux should be a no-brainer. I spent most of my |
| 14 | time on macOS finding solutions to make things work. Using [Brew](https://brew.sh/) | 14 | time on macOS finding solutions to make things work. Using |
| 15 | was just a horrible experience and far from package managers of Linux. At least | 15 | [Brew](https://brew.sh/) was just a horrible experience and far from package |
| 16 | they managed to get that `sudo` debacle sorted. | 16 | managers of Linux. At least they managed to get that `sudo` debacle sorted. |
| 17 | 17 | ||
| 18 | Not all was bad. macOS in general was a perfectly good environment. Things like | 18 | Not all was bad. macOS in general was a perfectly good environment. Things like |
| 19 | Docker and tooling like this worked without any hiccups. My normal tools like | 19 | Docker and tooling like this worked without any hiccups. My normal tools like |
| 20 | coding IDE worked flawlessly and the whole look and feel is just superb. I have | 20 | coding IDE worked flawlessly and the whole look and feel is just superb. I have |
| 21 | been using MacBook Air for couple of years so I was used to the system but | 21 | been using MacBook Air for couple of years so I was used to the system but never |
| 22 | never as a daily driver. | 22 | as a daily driver. |
| 23 | 23 | ||
| 24 | One of the things I did after I installed Linux back on my machine was cleaning | 24 | One of the things I did after I installed Linux back on my machine was cleaning |
| 25 | up my Dropbox folder. I have everything on Dropbox. Even projects folder. I | 25 | up my Dropbox folder. I have everything on Dropbox. Even projects folder. I |
| 26 | write code for living so my whole life revolves around couple of megs of code | 26 | write code for living so my whole life revolves around couple of megs of code |
| 27 | (with assets). So it's not like I have huge files on my machine. I don't have | 27 | (with assets). So it's not like I have huge files on my machine. I don't have |
| 28 | movies or music or pictures on my PC. All of that stuff is in cloud. I use | 28 | movies or music or pictures on my PC. All of that stuff is in cloud. I use |
| 29 | Google music and I have Netflix account which is more than enough for me. | 29 | Google music and I have Netflix account which is more than enough for me. |
| 30 | 30 | ||
| 31 | I also went and deleted some of the repositories on my Github account. I have | 31 | I also went and deleted some of the repositories on my Github account. I have |
| 32 | deleted more code than deployed. People find this strange but for me deleting | 32 | deleted more code than deployed. People find this strange but for me deleting |
| 33 | something feels so cathartic and also forces me to write better code next time | 33 | something feels so cathartic and also forces me to write better code next time |
| 34 | around when I am faced with similar problem. That was a huge relief if I am | 34 | around when I am faced with similar problem. That was a huge relief if I am |
| 35 | being totally honest. | 35 | being totally honest. |
| 36 | 36 | ||
| 37 | Next step was to do something with my webpage. I have been using some scripts | 37 | Next step was to do something with my webpage. I have been using some scripts I |
| 38 | I wrote a while ago to generate static pages from markdown source posts. I kept | 38 | wrote a while ago to generate static pages from markdown source posts. I kept on |
| 39 | on adding and adding stuff on top of it and it became a source of a | 39 | adding and adding stuff on top of it and it became a source of a |
| 40 | frustration. And this is just a simple blog and I was using gulp and npm. | 40 | frustration. And this is just a simple blog and I was using gulp and npm. |
| 41 | Anyways after couple of hours of searching and testing static generators I | 41 | Anyways after couple of hours of searching and testing static generators I found |
| 42 | found an interesting one [https://github.com/piranha/gostatic](https://github.com/piranha/gostatic) | 42 | an interesting one |
| 43 | and I just decided to use this one. It was the only one that had a simple | 43 | [https://github.com/piranha/gostatic](https://github.com/piranha/gostatic) and I |
| 44 | templating engine, not that I really need one. But others had this convoluted | 44 | just decided to use this one. It was the only one that had a simple templating |
| 45 | way of trying to solve everything and at the end just required quite bigger | 45 | engine, not that I really need one. But others had this convoluted way of trying |
| 46 | learning curve I was ready to go with. So I deleted couple of old posts, | 46 | to solve everything and at the end just required quite bigger learning curve I |
| 47 | simplified HTML, trashed most of the CSS and went with | 47 | was ready to go with. So I deleted couple of old posts, simplified HTML, trashed |
| 48 | [https://motherfuckingwebsite.com/](https://motherfuckingwebsite.com/) aesthetics. | 48 | most of the CSS and went with |
| 49 | Yeah, the previous site was more visually stimulating but all I really care is | 49 | [https://motherfuckingwebsite.com/](https://motherfuckingwebsite.com/) |
| 50 | the content at this point. And Times New Roman font is kind of awesome. | 50 | aesthetics. Yeah, the previous site was more visually stimulating but all I |
| 51 | 51 | really care is the content at this point. And Times New Roman font is kind of | |
| 52 | I stopped working on most of the projects in the past couple of months because | 52 | awesome. |
| 53 | the overhead was just too insane. There comes a point when you stretch yourself | 53 | |
| 54 | I stopped working on most of the projects in the past couple of months because | ||
| 55 | the overhead was just too insane. There comes a point when you stretch yourself | ||
| 54 | too much and then you stop progressing and with that comes dissatisfaction. | 56 | too much and then you stop progressing and with that comes dissatisfaction. |
| 55 | 57 | ||
| 56 | So that's about it. Moving forward minimal style. | 58 | So that's about it. Moving forward minimal style. |
| 57 | |||
diff --git a/content/posts/2019-10-19-using-sentiment-analysis-for-clickbait-detection.md b/content/posts/2019-10-19-using-sentiment-analysis-for-clickbait-detection.md index 995da25..e7324bb 100644 --- a/content/posts/2019-10-19-using-sentiment-analysis-for-clickbait-detection.md +++ b/content/posts/2019-10-19-using-sentiment-analysis-for-clickbait-detection.md | |||
| @@ -7,22 +7,22 @@ draft: false | |||
| 7 | 7 | ||
| 8 | ## Initial thoughts | 8 | ## Initial thoughts |
| 9 | 9 | ||
| 10 | One of the things that interested me for a while now is if major well | 10 | One of the things that interested me for a while now is if major well |
| 11 | established news sites use click bait titles to drive additional traffic | 11 | established news sites use click bait titles to drive additional traffic to |
| 12 | to their sites and generate additional impressions. | 12 | their sites and generate additional impressions. |
| 13 | 13 | ||
| 14 | Goal is to see how article titles and actual content of article differ from | 14 | Goal is to see how article titles and actual content of article differ from each |
| 15 | each other and see if titles are clickbaited. | 15 | other and see if titles are clickbaited. |
| 16 | 16 | ||
| 17 | ## Preparing and cleaning data | 17 | ## Preparing and cleaning data |
| 18 | 18 | ||
| 19 | For this example I opted to just use RSS feed from a new website and decided | 19 | For this example I opted to just use RSS feed from a new website and decided to |
| 20 | to go with [The Guardian](https://www.theguardian.com) World news. While this | 20 | go with [The Guardian](https://www.theguardian.com) World news. While this gets |
| 21 | gets us limited data (~40) articles and also description (actual content) is | 21 | us limited data (~40) articles and also description (actual content) is trimmed |
| 22 | trimmed this really doesn't reflect the actual article contents. | 22 | this really doesn't reflect the actual article contents. |
| 23 | 23 | ||
| 24 | To get better content I could use web scraping and use RSS as link list and | 24 | To get better content I could use web scraping and use RSS as link list and |
| 25 | fetch contents directly from website, but for this simple example this will | 25 | fetch contents directly from website, but for this simple example this will |
| 26 | suffice. | 26 | suffice. |
| 27 | 27 | ||
| 28 | There are couple of requirements we need to install before we continue: | 28 | There are couple of requirements we need to install before we continue: |
| @@ -50,12 +50,12 @@ for item in feed.entries: | |||
| 50 | Since we now have cleaned up data in our `feed.entries` object we can start with | 50 | Since we now have cleaned up data in our `feed.entries` object we can start with |
| 51 | performing sentiment analysis. | 51 | performing sentiment analysis. |
| 52 | 52 | ||
| 53 | There are many sentiment analysis libraries available that range from rule-based | 53 | There are many sentiment analysis libraries available that range from rule-based |
| 54 | sentiment analysis up to machine learning supported analysis. To keep things | 54 | sentiment analysis up to machine learning supported analysis. To keep things |
| 55 | simple I decided to use rule-based analysis library | 55 | simple I decided to use rule-based analysis library |
| 56 | [vaderSentiment](https://github.com/cjhutto/vaderSentiment) from | 56 | [vaderSentiment](https://github.com/cjhutto/vaderSentiment) from |
| 57 | [C.J. Hutto](https://github.com/cjhutto). Really nice library and quite | 57 | [C.J. Hutto](https://github.com/cjhutto). Really nice library and quite easy to |
| 58 | easy to use. | 58 | use. |
| 59 | 59 | ||
| 60 | ```python | 60 | ```python |
| 61 | from vaderSentiment.vaderSentiment import SentimentIntensityAnalyzer | 61 | from vaderSentiment.vaderSentiment import SentimentIntensityAnalyzer |
| @@ -68,9 +68,9 @@ for item in feed.entries: | |||
| 68 | sentiment_results.append([sentiment_title['compound'], sentiment_description['compound']]) | 68 | sentiment_results.append([sentiment_title['compound'], sentiment_description['compound']]) |
| 69 | ``` | 69 | ``` |
| 70 | 70 | ||
| 71 | Now that we have this data in a shape that is compatible with matplotlib we can | 71 | Now that we have this data in a shape that is compatible with matplotlib we can |
| 72 | plot results to see the difference between title and description sentiment of | 72 | plot results to see the difference between title and description sentiment of an |
| 73 | an article. | 73 | article. |
| 74 | 74 | ||
| 75 | ```python | 75 | ```python |
| 76 | import matplotlib.pyplot as plt | 76 | import matplotlib.pyplot as plt |
| @@ -85,15 +85,15 @@ plt.show() | |||
| 85 | ## Results and assets | 85 | ## Results and assets |
| 86 | 86 | ||
| 87 | 1. Because of the small sample size further conclusions are impossible to make. | 87 | 1. Because of the small sample size further conclusions are impossible to make. |
| 88 | 2. Rule-based approach may not be the best way of doing this. By using deep | 88 | 2. Rule-based approach may not be the best way of doing this. By using deep |
| 89 | learning we would be able to get better insights. | 89 | learning we would be able to get better insights. |
| 90 | 3. **Next step would be to** periodically fetch RSS items and store them over | 90 | 3. **Next step would be to** periodically fetch RSS items and store them over a |
| 91 | a longer period of time and then perform analysis again and use either | 91 | longer period of time and then perform analysis again and use either machine |
| 92 | machine learning or deep learning on top of it. | 92 | learning or deep learning on top of it. |
| 93 | 93 | ||
| 94 |  | 94 |  |
| 95 | 95 | ||
| 96 | Figure above displays difference between title and description sentiment for | 96 | Figure above displays difference between title and description sentiment for |
| 97 | specific RSS feed item. 1 means positive and -1 means negative sentiment. | 97 | specific RSS feed item. 1 means positive and -1 means negative sentiment. |
| 98 | 98 | ||
| 99 | [» Download Jupyter Notebook](/assets/sentiment-analysis/sentiment-analysis.ipynb) | 99 | [» Download Jupyter Notebook](/assets/sentiment-analysis/sentiment-analysis.ipynb) |
diff --git a/content/posts/2020-03-22-simple-sse-based-pubsub-server.md b/content/posts/2020-03-22-simple-sse-based-pubsub-server.md index 77c42a9..60745d0 100644 --- a/content/posts/2020-03-22-simple-sse-based-pubsub-server.md +++ b/content/posts/2020-03-22-simple-sse-based-pubsub-server.md | |||
| @@ -7,35 +7,35 @@ draft: false | |||
| 7 | 7 | ||
| 8 | ## Before we continue ... | 8 | ## Before we continue ... |
| 9 | 9 | ||
| 10 | Publisher Subscriber model is nothing new and there are many amazing solutions | 10 | Publisher Subscriber model is nothing new and there are many amazing solutions |
| 11 | out there, so writing a new one would be a waste of time if other solutions | 11 | out there, so writing a new one would be a waste of time if other solutions |
| 12 | wouldn't have quite complex install procedures and weren't so hard to maintain. | 12 | wouldn't have quite complex install procedures and weren't so hard to maintain. |
| 13 | But to be fair, comparing this simple server with something like | 13 | But to be fair, comparing this simple server with something like |
| 14 | [Kafka](https://kafka.apache.org/) or [RabbitMQ](https://www.rabbitmq.com/) is | 14 | [Kafka](https://kafka.apache.org/) or [RabbitMQ](https://www.rabbitmq.com/) is |
| 15 | laughable at the least. Those solutions are enterprise grade and have many | 15 | laughable at the least. Those solutions are enterprise grade and have many |
| 16 | mechanisms there to ensure messages aren't lost and much more. Regardless of | 16 | mechanisms there to ensure messages aren't lost and much more. Regardless of |
| 17 | these drawbacks, this method has been tested on a large website and worked | 17 | these drawbacks, this method has been tested on a large website and worked until |
| 18 | until now without any problems. So now, that we got that cleared up, let's | 18 | now without any problems. So now, that we got that cleared up, let's continue. |
| 19 | continue. | 19 | |
| 20 | 20 | ***Wiki definition:** Publish/subscribe messaging, or pub/sub messaging, is a | |
| 21 | ***Wiki definition:** Publish/subscribe messaging, or pub/sub messaging, is a | 21 | form of asynchronous service-to-service communication used in serverless and |
| 22 | form of asynchronous service-to-service communication used in serverless and | 22 | microservices architectures. In a pub/sub model, any message published to a |
| 23 | microservices architectures. In a pub/sub model, any message published to a | ||
| 24 | topic is immediately received by all the subscribers to the topic.* | 23 | topic is immediately received by all the subscribers to the topic.* |
| 25 | 24 | ||
| 26 | ## General goals | 25 | ## General goals |
| 27 | 26 | ||
| 28 | - provide a simple server that relays messages to all the connected clients, | 27 | - provide a simple server that relays messages to all the connected clients, |
| 29 | - messages can be posted on specific topics, | 28 | - messages can be posted on specific topics, |
| 30 | - messages get sent via [Server-Sent Events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events) | 29 | - messages get sent via [Server-Sent |
| 30 | Events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events) | ||
| 31 | to all the subscribers. | 31 | to all the subscribers. |
| 32 | 32 | ||
| 33 | ## How exactly does the pub/sub model work? | 33 | ## How exactly does the pub/sub model work? |
| 34 | 34 | ||
| 35 | The easiest way to explain this is with diagram bellow. Basic function is | 35 | The easiest way to explain this is with diagram bellow. Basic function is |
| 36 | simple. We have subscribers that receive messages, and we have publishers that | 36 | simple. We have subscribers that receive messages, and we have publishers that |
| 37 | create and post messages. Similar model is also well know pattern that works | 37 | create and post messages. Similar model is also well know pattern that works on |
| 38 | on a premise of consumers and producers, and they take similar roles. | 38 | a premise of consumers and producers, and they take similar roles. |
| 39 | 39 | ||
| 40 |  | 40 |  |
| 41 | 41 | ||
| @@ -45,43 +45,47 @@ on a premise of consumers and producers, and they take similar roles. | |||
| 45 | - consumer is receiving messages from subscribed topic, | 45 | - consumer is receiving messages from subscribed topic, |
| 46 | - servers is also known as Broker, | 46 | - servers is also known as Broker, |
| 47 | - broker does not store messages or tracks success, | 47 | - broker does not store messages or tracks success, |
| 48 | - broker uses [FIFO](https://en.wikipedia.org/wiki/FIFO_(computing_and_electronics)) | 48 | - broker uses |
| 49 | method for delivering messages, | 49 | [FIFO](https://en.wikipedia.org/wiki/FIFO_(computing_and_electronics)) method |
| 50 | - if consumer wants to receive messages from a topic, producer and consumer topics | 50 | for delivering messages, |
| 51 | must match, | 51 | - if consumer wants to receive messages from a topic, producer and consumer |
| 52 | topics must match, | ||
| 52 | - consumer can subscribe to multiple topics, | 53 | - consumer can subscribe to multiple topics, |
| 53 | - producer can publish to multiple topics, | 54 | - producer can publish to multiple topics, |
| 54 | - each message has a messageId. | 55 | - each message has a messageId. |
| 55 | 56 | ||
| 56 | **Known drawbacks:** | 57 | **Known drawbacks:** |
| 57 | 58 | ||
| 58 | - messages will not be stored in a persistent queue or unreceived messages like | 59 | - messages will not be stored in a persistent queue or unreceived messages like |
| 59 | [DeadLetterQueue](https://en.wikipedia.org/wiki/Dead_letter_queue) so old | 60 | [DeadLetterQueue](https://en.wikipedia.org/wiki/Dead_letter_queue) so old |
| 60 | messages could be lost on server restart, | 61 | messages could be lost on server restart, |
| 61 | - [Server-Sent Events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events) | 62 | - [Server-Sent |
| 62 | opens a long-running connection between the client and the server so make | 63 | Events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events) |
| 63 | sure if your setup is load balanced that the load balancer in this case can | 64 | opens a long-running connection between the client and the server so make sure |
| 64 | have long opened connection, | 65 | if your setup is load balanced that the load balancer in this case can have |
| 66 | long opened connection, | ||
| 65 | - no system moderation due to the dynamic nature of creating queues. | 67 | - no system moderation due to the dynamic nature of creating queues. |
| 66 | 68 | ||
| 67 | ## Server-Sent Events | 69 | ## Server-Sent Events |
| 68 | 70 | ||
| 69 | Read more about it on [official specification page](https://html.spec.whatwg.org/multipage/server-sent-events.html). | 71 | Read more about it on [official specification |
| 72 | page](https://html.spec.whatwg.org/multipage/server-sent-events.html). | ||
| 70 | 73 | ||
| 71 | ### Current browser support | 74 | ### Current browser support |
| 72 | 75 | ||
| 73 |  | 76 |  |
| 74 | 77 | ||
| 75 | Check [https://caniuse.com/#feat=eventsource](https://caniuse.com/#feat=eventsource) | 78 | Check |
| 79 | [https://caniuse.com/#feat=eventsource](https://caniuse.com/#feat=eventsource) | ||
| 76 | for latest information about browser support. | 80 | for latest information about browser support. |
| 77 | 81 | ||
| 78 | ### Known issues | 82 | ### Known issues |
| 79 | 83 | ||
| 80 | - Firefox 52 and below do not support EventSource in web/shared workers | 84 | - Firefox 52 and below do not support EventSource in web/shared workers |
| 81 | - In Firefox prior to version 36 server-sent events do not reconnect | 85 | - In Firefox prior to version 36 server-sent events do not reconnect |
| 82 | automatically in case of a connection interrupt (bug) | 86 | automatically in case of a connection interrupt (bug) |
| 83 | - Reportedly, CORS in EventSource is currently supported in Firefox 10+, | 87 | - Reportedly, CORS in EventSource is currently supported in Firefox 10+, Opera |
| 84 | Opera 12+, Chrome 26+, Safari 7.0+. | 88 | 12+, Chrome 26+, Safari 7.0+. |
| 85 | - Antivirus software may block the event streaming data chunks. | 89 | - Antivirus software may block the event streaming data chunks. |
| 86 | 90 | ||
| 87 | Source: [https://caniuse.com/#feat=eventsource](https://caniuse.com/#feat=eventsource) | 91 | Source: [https://caniuse.com/#feat=eventsource](https://caniuse.com/#feat=eventsource) |
| @@ -104,7 +108,7 @@ data: this is line two | |||
| 104 | <blank line> | 108 | <blank line> |
| 105 | ``` | 109 | ``` |
| 106 | 110 | ||
| 107 | And you can specify your own event types (the above messages will all trigger | 111 | And you can specify your own event types (the above messages will all trigger |
| 108 | the message event): | 112 | the message event): |
| 109 | 113 | ||
| 110 | ```bash | 114 | ```bash |
| @@ -116,7 +120,7 @@ data: 103.34 | |||
| 116 | 120 | ||
| 117 | ### Server requirements | 121 | ### Server requirements |
| 118 | 122 | ||
| 119 | The important thing is how you send headers and which headers are sent by the | 123 | The important thing is how you send headers and which headers are sent by the |
| 120 | server that triggers browser to threat response as a EventStream. | 124 | server that triggers browser to threat response as a EventStream. |
| 121 | 125 | ||
| 122 | Headers responsible for this are: | 126 | Headers responsible for this are: |
| @@ -129,23 +133,23 @@ Connection: keep-alive | |||
| 129 | 133 | ||
| 130 | ### Debugging with Google Chrome | 134 | ### Debugging with Google Chrome |
| 131 | 135 | ||
| 132 | Google Chrome provides build-in debugging and exploration tool for | 136 | Google Chrome provides build-in debugging and exploration tool for [Server-Sent |
| 133 | [Server-Sent Events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events) | 137 | Events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events) |
| 134 | which is quite nice and available from Developer Tools under Network tab. | 138 | which is quite nice and available from Developer Tools under Network tab. |
| 135 | 139 | ||
| 136 | > You can debug only client side events that get received and not the server | 140 | > You can debug only client side events that get received and not the server |
| 137 | > ones. For debugging server events add `console.log` to `server.js` code and | 141 | > ones. For debugging server events add `console.log` to `server.js` code and |
| 138 | > print out events. | 142 | > print out events. |
| 139 | 143 | ||
| 140 |  | 144 |  |
| 141 | 145 | ||
| 142 | ## Server implementation | 146 | ## Server implementation |
| 143 | 147 | ||
| 144 | For the sake of this example we will use [Node.js](https://nodejs.org/en/) | 148 | For the sake of this example we will use [Node.js](https://nodejs.org/en/) with |
| 145 | with [Express](https://expressjs.com) as our router since this is the easiest | 149 | [Express](https://expressjs.com) as our router since this is the easiest way to |
| 146 | way to get started and we will use already written SSE library for node | 150 | get started and we will use already written SSE library for node |
| 147 | [sse-pubsub](https://www.npmjs.com/package/sse-pubsub) so we don't reinvent | 151 | [sse-pubsub](https://www.npmjs.com/package/sse-pubsub) so we don't reinvent the |
| 148 | the wheel. | 152 | wheel. |
| 149 | 153 | ||
| 150 | ```bash | 154 | ```bash |
| 151 | npm init --yes | 155 | npm init --yes |
| @@ -252,16 +256,16 @@ app.listen(port, () => { | |||
| 252 | 256 | ||
| 253 | ### Our custom message format | 257 | ### Our custom message format |
| 254 | 258 | ||
| 255 | Each message posted on a server must be in a specific format that out server | 259 | Each message posted on a server must be in a specific format that out server |
| 256 | accepts. Having structure like this allows us to have multiple separated type | 260 | accepts. Having structure like this allows us to have multiple separated type of |
| 257 | of events on each topic. | 261 | events on each topic. |
| 258 | 262 | ||
| 259 | With this we can separate streams and only receive events that belong to the | 263 | With this we can separate streams and only receive events that belong to the |
| 260 | topic. | 264 | topic. |
| 261 | 265 | ||
| 262 | One example would be, that we have index page and we want to receive messages | 266 | One example would be, that we have index page and we want to receive messages |
| 263 | about new upvotes or new subscribers but we don't want to follow events for | 267 | about new upvotes or new subscribers but we don't want to follow events for |
| 264 | other pages. This reduces clutter and overall network. And structure is much | 268 | other pages. This reduces clutter and overall network. And structure is much |
| 265 | nicer and maintanable. | 269 | nicer and maintanable. |
| 266 | 270 | ||
| 267 | ```json | 271 | ```json |
| @@ -278,15 +282,15 @@ nicer and maintanable. | |||
| 278 | 282 | ||
| 279 | <video src="/assets/simple-pubsub-server/clients.m4v" controls></video> | 283 | <video src="/assets/simple-pubsub-server/clients.m4v" controls></video> |
| 280 | 284 | ||
| 281 | You can download [the code](../simple-pubsub-server/sse-pubsub-server.zip) | 285 | You can download [the code](../simple-pubsub-server/sse-pubsub-server.zip) and |
| 282 | and follow along. | 286 | follow along. |
| 283 | 287 | ||
| 284 | ### Publisher | 288 | ### Publisher |
| 285 | 289 | ||
| 286 | As talked about above publisher is the one that send messages to the | 290 | As talked about above publisher is the one that send messages to the |
| 287 | broker/server. Message inside the payload can be whatever you want (string, | 291 | broker/server. Message inside the payload can be whatever you want (string, |
| 288 | object, array). I would however personally avoid send large chunks of data | 292 | object, array). I would however personally avoid send large chunks of data like |
| 289 | like blobs and such. | 293 | blobs and such. |
| 290 | 294 | ||
| 291 | ```html | 295 | ```html |
| 292 | <!DOCTYPE html> | 296 | <!DOCTYPE html> |
| @@ -359,19 +363,19 @@ like blobs and such. | |||
| 359 | 363 | ||
| 360 | ### Subscriber | 364 | ### Subscriber |
| 361 | 365 | ||
| 362 | Subscriber is responsible for receiving new messages that come from server via | 366 | Subscriber is responsible for receiving new messages that come from server via |
| 363 | publisher. The code bellow is very rudimentary but works and follows the | 367 | publisher. The code bellow is very rudimentary but works and follows the |
| 364 | implementation guidelines for EventSource. | 368 | implementation guidelines for EventSource. |
| 365 | 369 | ||
| 366 | You can use either Developer Tools Console to see incoming messages or you can | 370 | You can use either Developer Tools Console to see incoming messages or you can |
| 367 | defer to Debugging with Google Chrome section above to see all EventStream | 371 | defer to Debugging with Google Chrome section above to see all EventStream |
| 368 | messages. | 372 | messages. |
| 369 | 373 | ||
| 370 | > Don't be alarmed if the subscriber gets disconnected from the server every | 374 | > Don't be alarmed if the subscriber gets disconnected from the server every so |
| 371 | > so often. The code we have here resets connection every 15s but it | 375 | > often. The code we have here resets connection every 15s but it automatically |
| 372 | > automatically get reconnected and fetches all messages up to last received | 376 | > get reconnected and fetches all messages up to last received message id. This |
| 373 | > message id. This setting can be adjusted in `server.js` file; search for | 377 | > setting can be adjusted in `server.js` file; search for the |
| 374 | > the `maxStreamDuration` variable. | 378 | > `maxStreamDuration` variable. |
| 375 | 379 | ||
| 376 | ```html | 380 | ```html |
| 377 | <!DOCTYPE html> | 381 | <!DOCTYPE html> |
diff --git a/content/posts/2020-03-27-create-placeholder-images-with-sharp.md b/content/posts/2020-03-27-create-placeholder-images-with-sharp.md index f7dd362..ac4f053 100644 --- a/content/posts/2020-03-27-create-placeholder-images-with-sharp.md +++ b/content/posts/2020-03-27-create-placeholder-images-with-sharp.md | |||
| @@ -5,14 +5,15 @@ date: 2020-03-27T12:00:00+02:00 | |||
| 5 | draft: false | 5 | draft: false |
| 6 | --- | 6 | --- |
| 7 | 7 | ||
| 8 | I have been searching for a solution to pre-generate some placeholder images | 8 | I have been searching for a solution to pre-generate some placeholder images for |
| 9 | for image server I needed to develop that resizes images on S3. I though this | 9 | image server I needed to develop that resizes images on S3. I though this would |
| 10 | would be a 15min job and quickly found out how very mistaken I was. | 10 | be a 15min job and quickly found out how very mistaken I was. |
| 11 | 11 | ||
| 12 | Even though Node.js is not really the best way to do this kind of things | 12 | Even though Node.js is not really the best way to do this kind of things (surely |
| 13 | (surely something written in C or Rust or even Golang would be the correct way | 13 | something written in C or Rust or even Golang would be the correct way to do |
| 14 | to do this but we didn't need the speed in our case) I found an excellent | 14 | this but we didn't need the speed in our case) I found an excellent library |
| 15 | library [sharp - High performance Node.js image processing](https://github.com/lovell/sharp). | 15 | [sharp - High performance Node.js image |
| 16 | processing](https://github.com/lovell/sharp). | ||
| 16 | 17 | ||
| 17 | Getting things running was a breeze. | 18 | Getting things running was a breeze. |
| 18 | 19 | ||
| @@ -53,20 +54,20 @@ s3.putObject({ | |||
| 53 | All this code was wrapped inside a web service with some additional security | 54 | All this code was wrapped inside a web service with some additional security |
| 54 | checks and defensive coding to detect if key is missing on S3. | 55 | checks and defensive coding to detect if key is missing on S3. |
| 55 | 56 | ||
| 56 | And at that point I needed to return placeholder images as a response in case | 57 | And at that point I needed to return placeholder images as a response in case |
| 57 | key is missing or x,y are not allowed by the server etc. I could have created | 58 | key is missing or x,y are not allowed by the server etc. I could have created |
| 58 | PNG in Gimp and just serve them but I wanted to respect aspect ratio and I | 59 | PNG in Gimp and just serve them but I wanted to respect aspect ratio and I |
| 59 | didn't want to return some mangled images. | 60 | didn't want to return some mangled images. |
| 60 | 61 | ||
| 61 | > Main problem with finding a clean solution I could copy and paste and change | 62 | > Main problem with finding a clean solution I could copy and paste and change a |
| 62 | a bit was a task. API is changing constantly and there weren't clear examples | 63 | > bit was a task. API is changing constantly and there weren't clear examples or |
| 63 | or I was unable to find them. | 64 | > I was unable to find them. |
| 64 | 65 | ||
| 65 | ## Generating placeholder images using SVG | 66 | ## Generating placeholder images using SVG |
| 66 | 67 | ||
| 67 | What I ended up was using SVG to generate text and created image with sharp and | 68 | What I ended up was using SVG to generate text and created image with sharp and |
| 68 | used composition to combine both layers. Response returned by this function is | 69 | used composition to combine both layers. Response returned by this function is a |
| 69 | a buffer you can use to either upload to S3 or save to local file. | 70 | buffer you can use to either upload to S3 or save to local file. |
| 70 | 71 | ||
| 71 | ```js | 72 | ```js |
| 72 | const generatePlaceholderImageWithText = async (width, height, message) => { | 73 | const generatePlaceholderImageWithText = async (width, height, message) => { |
| @@ -91,11 +92,10 @@ const generatePlaceholderImageWithText = async (width, height, message) => { | |||
| 91 | } | 92 | } |
| 92 | ``` | 93 | ``` |
| 93 | 94 | ||
| 94 | That is about it. Nothing more to it. You can change the color of the image by | 95 | That is about it. Nothing more to it. You can change the color of the image by |
| 95 | changing `background` and if you want to change text styling you can adapt | 96 | changing `background` and if you want to change text styling you can adapt SVG |
| 96 | SVG to your needs. | 97 | to your needs. |
| 97 | |||
| 98 | > Also be careful about the length of the text. This function positions text | ||
| 99 | > at the center and adds `20px` padding on all sides. If text is longer than | ||
| 100 | > the image it will get cut. | ||
| 101 | 98 | ||
| 99 | > Also be careful about the length of the text. This function positions text at | ||
| 100 | > the center and adds `20px` padding on all sides. If text is longer than the | ||
| 101 | > image it will get cut. | ||
diff --git a/content/posts/2020-03-29-the-strange-case-of-elasticsearch-allocation-failure.md b/content/posts/2020-03-29-the-strange-case-of-elasticsearch-allocation-failure.md index d0f4bac..bf1d710 100644 --- a/content/posts/2020-03-29-the-strange-case-of-elasticsearch-allocation-failure.md +++ b/content/posts/2020-03-29-the-strange-case-of-elasticsearch-allocation-failure.md | |||
| @@ -5,33 +5,33 @@ date: 2020-03-29T12:00:00+02:00 | |||
| 5 | draft: false | 5 | draft: false |
| 6 | --- | 6 | --- |
| 7 | 7 | ||
| 8 | I've been using Elasticsearch in production for 5 years now and never had a | 8 | I've been using Elasticsearch in production for 5 years now and never had a |
| 9 | single problem with it. Hell, never even known there could be a problem. Just | 9 | single problem with it. Hell, never even known there could be a problem. Just |
| 10 | worked. All this time. The first node that I deployed is still being used in | 10 | worked. All this time. The first node that I deployed is still being used in |
| 11 | production, never updated, upgraded, touched in anyway. | 11 | production, never updated, upgraded, touched in anyway. |
| 12 | 12 | ||
| 13 | All this bliss came to an abrupt end this Friday when I got notification that | 13 | All this bliss came to an abrupt end this Friday when I got notification that |
| 14 | Elasticsearch cluster went warm. Well, warm is not that bad right? Wrong! | 14 | Elasticsearch cluster went warm. Well, warm is not that bad right? Wrong! |
| 15 | Quickly after that I got another email which sent chills down my spine. | 15 | Quickly after that I got another email which sent chills down my spine. Cluster |
| 16 | Cluster is now red. RED! Now, shit really hit the fan! | 16 | is now red. RED! Now, shit really hit the fan! |
| 17 | 17 | ||
| 18 | I tried googling what could be the problem and after executing allocation | 18 | I tried googling what could be the problem and after executing allocation |
| 19 | function noticed that some shards were unassigned and 5 attempts were already | 19 | function noticed that some shards were unassigned and 5 attempts were already |
| 20 | made (which is BTW to my luck the maximum) and that meant I am basically fucked. | 20 | made (which is BTW to my luck the maximum) and that meant I am basically fucked. |
| 21 | They also applied that one should wait for cluster to re-balance itself. So, | 21 | They also applied that one should wait for cluster to re-balance itself. So, I |
| 22 | I waited. One hour, two hours, several hours. Nothing, still RED. | 22 | waited. One hour, two hours, several hours. Nothing, still RED. |
| 23 | 23 | ||
| 24 | The strangest thing about it all was, that queries were still being fulfilled. | 24 | The strangest thing about it all was, that queries were still being fulfilled. |
| 25 | Data was coming out. On the outside it looked like nothing was wrong but | 25 | Data was coming out. On the outside it looked like nothing was wrong but |
| 26 | everybody that would look at the cluster would know immediately that something | 26 | everybody that would look at the cluster would know immediately that something |
| 27 | was very very wrong and we were living on borrowed time here. | 27 | was very very wrong and we were living on borrowed time here. |
| 28 | 28 | ||
| 29 | > **Please, DO NOT do what I did.** Seriously! Please ask someone on official | 29 | > **Please, DO NOT do what I did.** Seriously! Please ask someone on official |
| 30 | forums or if you know an expert please consult him. There could be million of | 30 | forums or if you know an expert please consult him. There could be million of |
| 31 | reasons and these solution fit my problem. Maybe in your case it would | 31 | reasons and these solution fit my problem. Maybe in your case it would |
| 32 | disastrous. I had all the data backed up and even if I would fail spectacularly | 32 | disastrous. I had all the data backed up and even if I would fail spectacularly |
| 33 | I would be able to restore the data. It would be a huge pain and I would | 33 | I would be able to restore the data. It would be a huge pain and I would loose |
| 34 | loose couple of days but I had a plan B. | 34 | couple of days but I had a plan B. |
| 35 | 35 | ||
| 36 | Executing allocation and told me what the problem was but no clear solution yet. | 36 | Executing allocation and told me what the problem was but no clear solution yet. |
| 37 | 37 | ||
| @@ -39,14 +39,14 @@ Executing allocation and told me what the problem was but no clear solution yet. | |||
| 39 | GET /_cat/allocation?format=json | 39 | GET /_cat/allocation?format=json |
| 40 | ``` | 40 | ``` |
| 41 | 41 | ||
| 42 | I got a message that `ALLOCATION_FAILED` with additional info | 42 | I got a message that `ALLOCATION_FAILED` with additional info `failed to create |
| 43 | `failed to create shard, failure ioexception[failed to obtain in-memory shard lock]`. | 43 | shard, failure ioexception[failed to obtain in-memory shard lock]`. Well |
| 44 | Well splendid! I must also say that our cluster is capable more than enough | 44 | splendid! I must also say that our cluster is capable more than enough to handle |
| 45 | to handle the traffic. Also JVM memory pressure never was an issue. So what | 45 | the traffic. Also JVM memory pressure never was an issue. So what happened |
| 46 | happened really then? | 46 | really then? |
| 47 | 47 | ||
| 48 | I tried also re-routing failed ones with no success due to AWS restrictions | 48 | I tried also re-routing failed ones with no success due to AWS restrictions on |
| 49 | on having managed Elasticsearch cluster (they lock some of the functions). | 49 | having managed Elasticsearch cluster (they lock some of the functions). |
| 50 | 50 | ||
| 51 | ```yaml | 51 | ```yaml |
| 52 | POST /_cluster/reroute?retry_failed=true | 52 | POST /_cluster/reroute?retry_failed=true |
| @@ -60,10 +60,10 @@ I got a message that significantly reduced my options. | |||
| 60 | } | 60 | } |
| 61 | ``` | 61 | ``` |
| 62 | 62 | ||
| 63 | After that I went on a hunt again. I won't bother you with all the details | 63 | After that I went on a hunt again. I won't bother you with all the details |
| 64 | because hours/days went by until I was finally able to re-index the problematic | 64 | because hours/days went by until I was finally able to re-index the problematic |
| 65 | index and hoped for the best. Until that moment even re-indexing was giving | 65 | index and hoped for the best. Until that moment even re-indexing was giving me |
| 66 | me errors. | 66 | errors. |
| 67 | 67 | ||
| 68 | ```yaml | 68 | ```yaml |
| 69 | POST _reindex | 69 | POST _reindex |
| @@ -77,8 +77,8 @@ POST _reindex | |||
| 77 | } | 77 | } |
| 78 | ``` | 78 | ``` |
| 79 | 79 | ||
| 80 | I needed to do this multiple times to get all the documents re-indexed. Then | 80 | I needed to do this multiple times to get all the documents re-indexed. Then I |
| 81 | I dropped the original one with the following command. | 81 | dropped the original one with the following command. |
| 82 | 82 | ||
| 83 | ```yaml | 83 | ```yaml |
| 84 | DELETE /myindex | 84 | DELETE /myindex |
| @@ -98,10 +98,10 @@ POST _reindex | |||
| 98 | } | 98 | } |
| 99 | ``` | 99 | ``` |
| 100 | 100 | ||
| 101 | On the surface it looks like all is working but I have a long road in front | 101 | On the surface it looks like all is working but I have a long road in front of |
| 102 | of me to get all the things working again. Cluster now shows that it is in | 102 | me to get all the things working again. Cluster now shows that it is in Green |
| 103 | Green mode but I am also getting a notification that the cluster has | 103 | mode but I am also getting a notification that the cluster has processing status |
| 104 | processing status which could mean million of things. | 104 | which could mean million of things. |
| 105 | 105 | ||
| 106 | Godspeed! | 106 | Godspeed! |
| 107 | 107 | ||
diff --git a/content/posts/2020-03-30-my-love-and-hate-relationship-with-nodejs.md b/content/posts/2020-03-30-my-love-and-hate-relationship-with-nodejs.md index 47b95d5..daebb4c 100644 --- a/content/posts/2020-03-30-my-love-and-hate-relationship-with-nodejs.md +++ b/content/posts/2020-03-30-my-love-and-hate-relationship-with-nodejs.md | |||
| @@ -5,96 +5,95 @@ date: 2020-03-30T12:00:00+02:00 | |||
| 5 | draft: false | 5 | draft: false |
| 6 | --- | 6 | --- |
| 7 | 7 | ||
| 8 | Previous project I was working on was being coded in [Golang](https://golang.org/). | 8 | Previous project I was working on was being coded in |
| 9 | Also was my first project using it. And damn, that was an awesome experience. | 9 | [Golang](https://golang.org/). Also was my first project using it. And damn, |
| 10 | The whole thing is just superb. From how errors are handled. The C-like way | 10 | that was an awesome experience. The whole thing is just superb. From how errors |
| 11 | you handle compiling. The way the language is structured making it incredibly | 11 | are handled. The C-like way you handle compiling. The way the language is |
| 12 | versatile and easy to learn. | 12 | structured making it incredibly versatile and easy to learn. |
| 13 | 13 | ||
| 14 | It may cause some pain for somebody that is not used of using interfaces to map | 14 | It may cause some pain for somebody that is not used of using interfaces to map |
| 15 | JSON and doing the recompilation all the time. But we have tools like | 15 | JSON and doing the recompilation all the time. But we have tools like |
| 16 | [entr](http://eradman.com/entrproject/) and [make](https://www.gnu.org/software/make/) | 16 | [entr](http://eradman.com/entrproject/) and |
| 17 | to fix that. | 17 | [make](https://www.gnu.org/software/make/) to fix that. |
| 18 | 18 | ||
| 19 | But we are not here to talk about my undying love for **Golang**. Only in some | 19 | But we are not here to talk about my undying love for **Golang**. Only in some |
| 20 | way we probably should. It is an excellent example of how modern language | 20 | way we probably should. It is an excellent example of how modern language should |
| 21 | should be designed. And because I have used it extensively in the last couple | 21 | be designed. And because I have used it extensively in the last couple of years |
| 22 | of years this probably taints my views of other languages. And is doing me a | 22 | this probably taints my views of other languages. And is doing me a great |
| 23 | great disservice. Nevertheless, here we are. | 23 | disservice. Nevertheless, here we are. |
| 24 | 24 | ||
| 25 | About two years ago I started flirting with [Node.js](https://nodejs.org/en/) | 25 | About two years ago I started flirting with [Node.js](https://nodejs.org/en/) |
| 26 | for a project I started working on. What I wanted was to have things written | 26 | for a project I started working on. What I wanted was to have things written in |
| 27 | in a language that is widely used, and we could get additional developers for. | 27 | a language that is widely used, and we could get additional developers for. As |
| 28 | As much as **Golang** is amazing it's really hard to get developers for it. | 28 | much as **Golang** is amazing it's really hard to get developers for it. Even |
| 29 | Even now. And after playing around with it for a week I felt in love with the | 29 | now. And after playing around with it for a week I felt in love with the speed |
| 30 | speed of iteration and massive package ecosystem. Do you want SSO? You got it! | 30 | of iteration and massive package ecosystem. Do you want SSO? You got it! Do you |
| 31 | Do you want some esoteric library for something? There is a strong chance | 31 | want some esoteric library for something? There is a strong chance somebody |
| 32 | somebody wrote it. It is so extensive that you find yourself evaluating | 32 | wrote it. It is so extensive that you find yourself evaluating packages based on |
| 33 | packages based on **GitHub stars** and number of contributors. You get | 33 | **GitHub stars** and number of contributors. You get swallowed by the vanity |
| 34 | swallowed by the vanity metrics and that potentially will become the downfall | 34 | metrics and that potentially will become the downfall of Node.js. |
| 35 | of Node.js. | 35 | |
| 36 | 36 | Because of the sheer amount of choice I often got anxiety when choosing | |
| 37 | Because of the sheer amount of choice I often got anxiety when choosing | 37 | libraries. Will I choose the correct one? Is this library something that will be |
| 38 | libraries. Will I choose the correct one? Is this library something that will | 38 | supported for a foreseeable future or not? I am used of using libraries that are |
| 39 | be supported for a foreseeable future or not? I am used of using libraries that | 39 | being in development for 10 years plus (Python, C) and that gave me some sort of |
| 40 | are being in development for 10 years plus (Python, C) and that gave me some | 40 | comfort. And it is probably unfair to Node.js and community to expect same |
| 41 | sort of comfort. And it is probably unfair to Node.js and community to expect | 41 | dedication. |
| 42 | same dedication. | 42 | |
| 43 | 43 | Moving forward ... Work started and things were great. **Speed of iteration was | |
| 44 | Moving forward ... Work started and things were great. | 44 | insane**. For some feature that I would need a day in Golang only took me hour |
| 45 | **Speed of iteration was insane**. For some feature that I would need a day | 45 | or two. I became lazy! Using packages all over the place. Falling into the same |
| 46 | in Golang only took me hour or two. I became lazy! Using packages all over | 46 | trap as others. Packages on top of packages. And [npm](https://www.npmjs.com/) |
| 47 | the place. Falling into the same trap as others. Packages on top of packages. | 47 | didn't help at all. The way that the package manager works is just |
| 48 | And [npm](https://www.npmjs.com/) didn't help at all. The way that the package | 48 | horrendous. And not allowing to have node_modules outside the project is also |
| 49 | manager works is just horrendous. And not allowing to have node_modules outside | 49 | the stupidest idea ever. |
| 50 | the project is also the stupidest idea ever. | 50 | |
| 51 | 51 | So at that point I started feeling the technical debt that comes with Node.js | |
| 52 | So at that point I started feeling the technical debt that comes with Node.js | 52 | and the whole ecosystem. What nobody tells you is that **structuring large |
| 53 | and the whole ecosystem. What nobody tells you is that | 53 | Node.js apps** is more problematic than one would think. And going microservice |
| 54 | **structuring large Node.js apps** is more problematic than one would think. | 54 | for every single thing is also a bad idea. The amount of networking you |
| 55 | And going microservice for every single thing is also a bad idea. The amount | 55 | introduce with that approach always ends up being a pain in the ass. And I don't |
| 56 | of networking you introduce with that approach always ends up being a pain in | 56 | even want to go into system administration here. The overhead is |
| 57 | the ass. And I don't even want to go into system administration here. The | 57 | insane. Package-lock.json made many days feel like living hell for me. And I |
| 58 | overhead is insane. Package-lock.json made many days feel like living hell | 58 | would eat the cost of all this if it meant for better development |
| 59 | for me. And I would eat the cost of all this if it meant for better development | ||
| 60 | experience. Well, it didn't. | 59 | experience. Well, it didn't. |
| 61 | 60 | ||
| 62 | The **lack of Typescript** support in the interpreter is still mind boggling | 61 | The **lack of Typescript** support in the interpreter is still mind boggling to |
| 63 | to me. Why haven't they added native support yet for this is beyond me?! That | 62 | me. Why haven't they added native support yet for this is beyond me?! That would |
| 64 | would have solved so many problems. Lack of type safety became a problem | 63 | have solved so many problems. Lack of type safety became a problem somewhere in |
| 65 | somewhere in the middle of the project where the codebase was sufficiently | 64 | the middle of the project where the codebase was sufficiently large enough to |
| 66 | large enough to present problems. We started adding arguments to functions | 65 | present problems. We started adding arguments to functions and there was **no |
| 67 | and there was **no way to implicitly define argument types**. And because at | 66 | way to implicitly define argument types**. And because at that point there were |
| 68 | that point there were a lot of functions, it became impossible to know what | 67 | a lot of functions, it became impossible to know what each one accepts, |
| 69 | each one accepts, development became more and more trial and error based. | 68 | development became more and more trial and error based. |
| 70 | 69 | ||
| 71 | I tried **implementing Typescript**, but that would present a large refactor | 70 | I tried **implementing Typescript**, but that would present a large refactor |
| 72 | that we were not willing to do at that point. The benefits were not enough. | 71 | that we were not willing to do at that point. The benefits were not enough. I |
| 73 | I also tried [Flow - static type checker](https://flow.org/) but implementation | 72 | also tried [Flow - static type checker](https://flow.org/) but implementation |
| 74 | was also horrible. What Typescript and Flow forces you is to have src folder | 73 | was also horrible. What Typescript and Flow forces you is to have src folder and |
| 75 | and then **transpile** your code into dist folder and run it with node. WTH is | 74 | then **transpile** your code into dist folder and run it with node. WTH is that |
| 76 | that all about. Why can't this be done in memory or some virtual file system? | 75 | all about. Why can't this be done in memory or some virtual file system? Why? I |
| 77 | Why? I see no reason why this couldn't be done like this. But it is what it is. | 76 | see no reason why this couldn't be done like this. But it is what it is. I |
| 78 | I abandoned all hope for static type checking. | 77 | abandoned all hope for static type checking. |
| 79 | 78 | ||
| 80 | One of the problems that resulted from not having interfaces or types was | 79 | One of the problems that resulted from not having interfaces or types was |
| 81 | inability to model out our data from **Elasticsearch**. I could have done | 80 | inability to model out our data from **Elasticsearch**. I could have done a |
| 82 | a **pedestrian implementation** of it, but there must be a better way of doing | 81 | **pedestrian implementation** of it, but there must be a better way of doing |
| 83 | this without resorting to some hack basically. Or maybe I haven't found a | 82 | this without resorting to some hack basically. Or maybe I haven't found a |
| 84 | solution, which is also a possibility. I have looked, though. No juice! | 83 | solution, which is also a possibility. I have looked, though. No juice! |
| 85 | 84 | ||
| 86 | **Error handling?** Is that a joke? | 85 | **Error handling?** Is that a joke? |
| 87 | 86 | ||
| 88 | Thank god for **await/async**. Without it, I would have probably just abandoned | 87 | Thank god for **await/async**. Without it, I would have probably just abandoned |
| 89 | the whole thing and went with something else like Python. That's all I am | 88 | the whole thing and went with something else like Python. That's all I am going |
| 90 | going to say about this :) | 89 | to say about this :) |
| 91 | 90 | ||
| 92 | I started asking myself a question if Node.js is actually ready to be used in | 91 | I started asking myself a question if Node.js is actually ready to be used in a |
| 93 | a **large scale applications**? And this was a totally wrong question. What I | 92 | **large scale applications**? And this was a totally wrong question. What I |
| 94 | should have been asking myself was, how to use Node.js in large scale | 93 | should have been asking myself was, how to use Node.js in large scale |
| 95 | application. And you don't get this in **marketing material** for Express or | 94 | application. And you don't get this in **marketing material** for Express or Koa |
| 96 | Koa etc. They never tell you this. Making Node.js scale on infrastructure or | 95 | etc. They never tell you this. Making Node.js scale on infrastructure or in |
| 97 | in codebase is really **more of an art than a science**. And just like with the | 96 | codebase is really **more of an art than a science**. And just like with the |
| 98 | whole JavaScript ecosystem: | 97 | whole JavaScript ecosystem: |
| 99 | 98 | ||
| 100 | - impossible to master, | 99 | - impossible to master, |
| @@ -103,10 +102,9 @@ whole JavaScript ecosystem: | |||
| 103 | - error handling is a joke, | 102 | - error handling is a joke, |
| 104 | - standards? What standards? | 103 | - standards? What standards? |
| 105 | 104 | ||
| 106 | But on the other hand. As I did, you will also learn to love it. Learn to use | 105 | But on the other hand. As I did, you will also learn to love it. Learn to use it |
| 107 | it quickly and do impossible things in crazy limited time. | 106 | quickly and do impossible things in crazy limited time. |
| 108 | 107 | ||
| 109 | I hate to admit it. But I love Node.js. Dammit, I love it :) | 108 | I hate to admit it. But I love Node.js. Dammit, I love it :) |
| 110 | 109 | ||
| 111 | 2023 Update: I hate Node.js! | 110 | 2023 Update: I hate Node.js! |
| 112 | |||
diff --git a/content/posts/2020-05-05-remote-work.md b/content/posts/2020-05-05-remote-work.md index 54a7d1b..90fca24 100644 --- a/content/posts/2020-05-05-remote-work.md +++ b/content/posts/2020-05-05-remote-work.md | |||
| @@ -5,29 +5,29 @@ date: 2020-05-05T12:00:00+02:00 | |||
| 5 | draft: false | 5 | draft: false |
| 6 | --- | 6 | --- |
| 7 | 7 | ||
| 8 | I have been working remotely for the past 5 years. I love it. Love the freedom | 8 | I have been working remotely for the past 5 years. I love it. Love the freedom |
| 9 | and make your schedule thingy. | 9 | and make your schedule thingy. |
| 10 | 10 | ||
| 11 | ## You work more not less | 11 | ## You work more not less |
| 12 | 12 | ||
| 13 | I've heard from people things like: "Oh, you are so lucky, working from home, | 13 | I've heard from people things like: "Oh, you are so lucky, working from home, |
| 14 | having all the free time you want". It was obvious they had no clue what means | 14 | having all the free time you want". It was obvious they had no clue what means |
| 15 | working remotely. They had this romantic idea of remote work. You can watch TV | 15 | working remotely. They had this romantic idea of remote work. You can watch TV |
| 16 | whenever you like, you can go outside for a picnic if you want and stuff like | 16 | whenever you like, you can go outside for a picnic if you want and stuff like |
| 17 | that. | 17 | that. |
| 18 | 18 | ||
| 19 | This may be true if you work a day or two in a week from home. But if you go | 19 | This may be true if you work a day or two in a week from home. But if you go |
| 20 | completely remote all these changes completely. I take some time to acclimate | 20 | completely remote all these changes completely. I take some time to acclimate |
| 21 | but then you start feeling the consequences of going fully remote. And it's not | 21 | but then you start feeling the consequences of going fully remote. And it's not |
| 22 | all rainbows and unicorns. Rather the opposite. | 22 | all rainbows and unicorns. Rather the opposite. |
| 23 | 23 | ||
| 24 | ## Feeling lost | 24 | ## Feeling lost |
| 25 | 25 | ||
| 26 | At first, I remembered I felt lost. I was not used to this kind of environment. | 26 | At first, I remembered I felt lost. I was not used to this kind of environment. |
| 27 | It felt disoriented and a part of you that is used to procrastinate turns on. | 27 | It felt disoriented and a part of you that is used to procrastinate turns on. |
| 28 | You start thinking of a workday as a whole day. And soon this idea of "I can do | 28 | You start thinking of a workday as a whole day. And soon this idea of "I can do |
| 29 | this later" starts creeping in. Well, I have the whole day ahead of me. I can | 29 | this later" starts creeping in. Well, I have the whole day ahead of me. I can do |
| 30 | do this a bit later. | 30 | this a bit later. |
| 31 | 31 | ||
| 32 | ## Hyper-performance | 32 | ## Hyper-performance |
| 33 | 33 | ||
| @@ -35,36 +35,37 @@ As a direct result, you become more focused on your work since you don't have | |||
| 35 | all the interruptions common in the workplace. And you can quickly get used to | 35 | all the interruptions common in the workplace. And you can quickly get used to |
| 36 | this hyper-performance. But this mode requires also a lot of peace and quiet. | 36 | this hyper-performance. But this mode requires also a lot of peace and quiet. |
| 37 | 37 | ||
| 38 | And here we come to the ugly parts of all this. **People rarely have the self-control** | 38 | And here we come to the ugly parts of all this. **People rarely have the |
| 39 | to not waste other people's time. It is paralyzing when people start calling | 39 | self-control** to not waste other people's time. It is paralyzing when people |
| 40 | you, sending you chat messages, etc. The thing is, that when I achieve this | 40 | start calling you, sending you chat messages, etc. The thing is, that when I |
| 41 | hyper-performance mode I am completely embroiled in the problem I am solving | 41 | achieve this hyper-performance mode I am completely embroiled in the problem I |
| 42 | and this kind of interruptions mess with your head. I need an hour at least to | 42 | am solving and this kind of interruptions mess with your head. I need an hour at |
| 43 | get back in the zone. Sometimes not achieving the same focus the whole day. | 43 | least to get back in the zone. Sometimes not achieving the same focus the whole |
| 44 | day. | ||
| 44 | 45 | ||
| 45 | I know that life is not how you want it to be and takes its route but from what | 46 | I know that life is not how you want it to be and takes its route but from what |
| 46 | I've learned this kind of interruptions can be avoided in 90% of the case | 47 | I've learned this kind of interruptions can be avoided in 90% of the case easily |
| 47 | easily just by closing any chat programs and putting your phone in a drawer. | 48 | just by closing any chat programs and putting your phone in a drawer. |
| 48 | 49 | ||
| 49 | ## Suggestion to all the new remote workers | 50 | ## Suggestion to all the new remote workers |
| 50 | 51 | ||
| 51 | - Stop wasting other people's time. You don't bother people at their desks | 52 | - Stop wasting other people's time. You don't bother people at their desks in |
| 52 | in the office either. | 53 | the office either. |
| 53 | - Do not replace daily chats in the hallways with instant messaging software. | 54 | - Do not replace daily chats in the hallways with instant messaging software. |
| 54 | It will only interrupt people. Nothing good will come of it. | 55 | It will only interrupt people. Nothing good will come of it. |
| 55 | - Set your working hours and try to not allow it to bleed outside these | 56 | - Set your working hours and try to not allow it to bleed outside these |
| 56 | boundaries and maintain your routine. | 57 | boundaries and maintain your routine. |
| 57 | - Be prepared that hours will be longer regardless of your good intentions | 58 | - Be prepared that hours will be longer regardless of your good intentions and |
| 58 | and your well thought of routine. | 59 | your well thought of routine. |
| 59 | - Try to be hyper-focused and do only one thing at the time. Multitasking is | 60 | - Try to be hyper-focused and do only one thing at the time. Multitasking is the |
| 60 | the enemy of progress. | 61 | enemy of progress. |
| 61 | - Avoid long meetings and if possible eliminate them. Rather take time to write | 62 | - Avoid long meetings and if possible eliminate them. Rather take time to write |
| 62 | them out and allow others to respond in their own time. Meetings are usually a | 63 | them out and allow others to respond in their own time. Meetings are usually a |
| 63 | large waste of time and most of the people attending them are there just | 64 | large waste of time and most of the people attending them are there just |
| 64 | because the manager said so. | 65 | because the manager said so. |
| 65 | - The software will not solve your problems. And throwing money at problems neither. | 66 | - The software will not solve your problems. And throwing money at problems |
| 66 | - If you are in a managerial position don't supervise any single minute of | 67 | neither. |
| 67 | workers. They are probably giving you more hours anyways. Track progress | 68 | - If you are in a managerial position don't supervise any single minute of |
| 69 | workers. They are probably giving you more hours anyways. Track progress | ||
| 68 | weekly not daily. You hired them and give them the benefit of the doubt that | 70 | weekly not daily. You hired them and give them the benefit of the doubt that |
| 69 | they will deliver what you agreed upon. | 71 | they will deliver what you agreed upon. |
| 70 | |||
diff --git a/content/posts/2020-08-15-systemd-disable-wake-onmouse.md b/content/posts/2020-08-15-systemd-disable-wake-onmouse.md index fabdc32..55086b1 100644 --- a/content/posts/2020-08-15-systemd-disable-wake-onmouse.md +++ b/content/posts/2020-08-15-systemd-disable-wake-onmouse.md | |||
| @@ -5,39 +5,41 @@ date: 2020-08-15T12:00:00+02:00 | |||
| 5 | draft: false | 5 | draft: false |
| 6 | --- | 6 | --- |
| 7 | 7 | ||
| 8 | I recently bought [ThinkPad X220](https://www.laptopmag.com/reviews/laptops/lenovo-thinkpad-x220) | 8 | I recently bought [ThinkPad |
| 9 | just as a joke on eBay to test Linux distributions and play around with things | 9 | X220](https://www.laptopmag.com/reviews/laptops/lenovo-thinkpad-x220) just as a |
| 10 | and not destroy my main machine. Little to my knowledge I felt in love with it. | 10 | joke on eBay to test Linux distributions and play around with things and not |
| 11 | Man, they really made awesome machines back then. | 11 | destroy my main machine. Little to my knowledge I felt in love with it. Man, |
| 12 | they really made awesome machines back then. | ||
| 12 | 13 | ||
| 13 | After changing disk that came with it to SSD and installing Ubuntu to test if | 14 | After changing disk that came with it to SSD and installing Ubuntu to test if |
| 14 | everything works I noticed that even after a single touch of my external mouse | 15 | everything works I noticed that even after a single touch of my external mouse |
| 15 | the system would wake up from sleep even though the lid was shut down. | 16 | the system would wake up from sleep even though the lid was shut down. |
| 16 | 17 | ||
| 17 | I wouldn't even noticed it if laptop didn't have | 18 | I wouldn't even noticed it if laptop didn't have [LED |
| 18 | [LED sleep indicator](https://support.lenovo.com/lk/en/solutions/~/media/Images/ContentImages/p/pd025386_x1_status_03.ashx?w=426&h=262). | 19 | sleep indicator](https://support.lenovo.com/lk/en/solutions/~/media/Images/ContentImages/p/pd025386_x1_status_03.ashx?w=426&h=262). |
| 19 | I already had a bad experience with Linux and it's power management. I had a | 20 | I already had a bad experience with Linux and it's power management. I had a |
| 20 | [Dell Inspiron 7537](https://www.pcmag.com/reviews/dell-inspiron-15-7537) laptop | 21 | [Dell Inspiron 7537](https://www.pcmag.com/reviews/dell-inspiron-15-7537) laptop |
| 21 | with a touchscreen and while traveling it decided to wake up and started cooking | 22 | with a touchscreen and while traveling it decided to wake up and started cooking |
| 22 | in my backpack to the point that the digitizer responsible for touch actually | 23 | in my backpack to the point that the digitizer responsible for touch actually |
| 23 | glue off and the whole screen got wrecked. So, I am a bit touchy about this. | 24 | glue off and the whole screen got wrecked. So, I am a bit touchy about this. |
| 24 | 25 | ||
| 25 | I went on solution hunting and to my surprise there is no easy way to disable | 26 | I went on solution hunting and to my surprise there is no easy way to disable |
| 26 | specific devices to perform wake up. Why is this not under the power management | 27 | specific devices to perform wake up. Why is this not under the power management |
| 27 | tab in setting is really strange. | 28 | tab in setting is really strange. |
| 28 | 29 | ||
| 29 | After googling for a solution I found [this nice article describing the solution](https://codetrips.com/2020/03/18/ubuntu-disable-mouse-wake-from-suspend/) | 30 | After googling for a solution I found [this nice article describing the |
| 30 | that worked for me. The only problem with this solution was that he added his | 31 | solution](https://codetrips.com/2020/03/18/ubuntu-disable-mouse-wake-from-suspend/) |
| 31 | solution to `.bashrc` and this triggers `sudo` that asks for a password each | 32 | that worked for me. The only problem with this solution was that he added his |
| 32 | time new terminal is opened, which get annoying quickly since I open a lot of | 33 | solution to `.bashrc` and this triggers `sudo` that asks for a password each |
| 34 | time new terminal is opened, which get annoying quickly since I open a lot of | ||
| 33 | terminals all the time. | 35 | terminals all the time. |
| 34 | 36 | ||
| 35 | I followed his instructions and got to solution | 37 | I followed his instructions and got to solution `sudo sh -c "echo 'disabled' > |
| 36 | `sudo sh -c "echo 'disabled' > /sys/bus/usb/devices/2-1.1/power/wakeup"`. | 38 | /sys/bus/usb/devices/2-1.1/power/wakeup"`. |
| 37 | 39 | ||
| 38 | I created a system service file `sudo nano /etc/systemd/system/disable-mouse-wakeup.service` | 40 | I created a system service file `sudo nano |
| 39 | and removed `sudo` and replaced `sh` with `/usr/bin/sh` and pasted all that | 41 | /etc/systemd/system/disable-mouse-wakeup.service` and removed `sudo` and |
| 40 | in `ExecStart`. | 42 | replaced `sh` with `/usr/bin/sh` and pasted all that in `ExecStart`. |
| 41 | 43 | ||
| 42 | ```ini | 44 | ```ini |
| 43 | [Unit] | 45 | [Unit] |
| @@ -68,4 +70,3 @@ This will permanently disable that device from wakeing up you computer on boot. | |||
| 68 | If you have many devices you would like to surpress from waking up your machine | 70 | If you have many devices you would like to surpress from waking up your machine |
| 69 | I would create a shell script and call that instead of direclty doing it in | 71 | I would create a shell script and call that instead of direclty doing it in |
| 70 | service file. | 72 | service file. |
| 71 | |||
diff --git a/content/posts/2020-09-06-esp-and-micropython.md b/content/posts/2020-09-06-esp-and-micropython.md index ac79a6d..91a04ad 100644 --- a/content/posts/2020-09-06-esp-and-micropython.md +++ b/content/posts/2020-09-06-esp-and-micropython.md | |||
| @@ -7,14 +7,16 @@ draft: false | |||
| 7 | 7 | ||
| 8 | ## Introduction | 8 | ## Introduction |
| 9 | 9 | ||
| 10 | A while ago I bought some [ESP8266](https://www.espressif.com/en/products/socs/esp8266) | 10 | A while ago I bought some |
| 11 | and [ESP32](https://www.espressif.com/en/products/socs/esp32) dev boards to | 11 | [ESP8266](https://www.espressif.com/en/products/socs/esp8266) and |
| 12 | play around with and I finally found a project to try it out. | 12 | [ESP32](https://www.espressif.com/en/products/socs/esp32) dev boards to play |
| 13 | around with and I finally found a project to try it out. | ||
| 13 | 14 | ||
| 14 | For my project, I used [ESP32](https://www.espressif.com/en/products/socs/esp32) | 15 | For my project, I used [ESP32](https://www.espressif.com/en/products/socs/esp32) |
| 15 | but I could easily choose [ESP8266](https://www.espressif.com/en/products/socs/esp8266). | 16 | but I could easily choose |
| 16 | This guide contains which tools I use and how I prepared my workspace to code | 17 | [ESP8266](https://www.espressif.com/en/products/socs/esp8266). This guide |
| 17 | for [ESP8266](https://www.espressif.com/en/products/socs/esp8266). | 18 | contains which tools I use and how I prepared my workspace to code for |
| 19 | [ESP8266](https://www.espressif.com/en/products/socs/esp8266). | ||
| 18 | 20 | ||
| 19 |  | 21 |  |
| 20 | 22 | ||
| @@ -29,16 +31,18 @@ mine and once I replaced it everything started to work. | |||
| 29 | 31 | ||
| 30 | ## Flashing the SOC | 32 | ## Flashing the SOC |
| 31 | 33 | ||
| 32 | Plug your ESP8266 to USB port and check if the device was recognized with | 34 | Plug your ESP8266 to USB port and check if the device was recognized with |
| 33 | executing `dmesg | grep ch341-uart`. | 35 | executing `dmesg | grep ch341-uart`. |
| 34 | 36 | ||
| 35 | Then check if the device is available under `/dev/` by running `ls /dev/ttyUSB*`. | 37 | Then check if the device is available under `/dev/` by running `ls |
| 38 | /dev/ttyUSB*`. | ||
| 36 | 39 | ||
| 37 | > **Linux users**: if a device is not available be sure you are in `dialout` | 40 | > **Linux users**: if a device is not available be sure you are in `dialout` |
| 38 | > group. You can check this by executing `groups $USER`. You can add a user to | 41 | > group. You can check this by executing `groups $USER`. You can add a user to |
| 39 | > `dialout` group with `sudo adduser $USER dialout`. | 42 | > `dialout` group with `sudo adduser $USER dialout`. |
| 40 | 43 | ||
| 41 | After these conditions are meet go to the navigate to [https://micropython.org/download/esp8266/](https://micropython.org/download/esp8266/) | 44 | After these conditions are meet go to the navigate to |
| 45 | [https://micropython.org/download/esp8266/](https://micropython.org/download/esp8266/) | ||
| 42 | and download `esp8266-20200902-v1.13.bin`. | 46 | and download `esp8266-20200902-v1.13.bin`. |
| 43 | 47 | ||
| 44 | ```sh | 48 | ```sh |
| @@ -48,14 +52,15 @@ cd esp8266-test | |||
| 48 | wget https://micropython.org/resources/firmware/esp8266-20200902-v1.13.bin | 52 | wget https://micropython.org/resources/firmware/esp8266-20200902-v1.13.bin |
| 49 | ``` | 53 | ``` |
| 50 | 54 | ||
| 51 | After obtaining firmware we will need some tooling to flash the firmware to | 55 | After obtaining firmware we will need some tooling to flash the firmware to the |
| 52 | the board. | 56 | board. |
| 53 | 57 | ||
| 54 | ```sh | 58 | ```sh |
| 55 | sudo pip3 install esptool | 59 | sudo pip3 install esptool |
| 56 | ``` | 60 | ``` |
| 57 | 61 | ||
| 58 | You can read more about `esptool` at [https://github.com/espressif/esptool/](https://github.com/espressif/esptool/). | 62 | You can read more about `esptool` at |
| 63 | [https://github.com/espressif/esptool/](https://github.com/espressif/esptool/). | ||
| 59 | 64 | ||
| 60 | Before flashing the firmware we need to erase the flash on device. Substitute | 65 | Before flashing the firmware we need to erase the flash on device. Substitute |
| 61 | `USB0` with the device listed in output of `ls /dev/ttyUSB*`. | 66 | `USB0` with the device listed in output of `ls /dev/ttyUSB*`. |
| @@ -70,8 +75,8 @@ If flash was successfully erased it is now time to flash the new firmware to it. | |||
| 70 | esptool.py --port /dev/ttyUSB0 --baud 460800 write_flash --flash_size=detect 0 esp8266-20200902-v1.13.bin | 75 | esptool.py --port /dev/ttyUSB0 --baud 460800 write_flash --flash_size=detect 0 esp8266-20200902-v1.13.bin |
| 71 | ``` | 76 | ``` |
| 72 | 77 | ||
| 73 | If everything went ok you can try accessing MicroPython REPL with ` | 78 | If everything went ok you can try accessing MicroPython REPL with ` screen |
| 74 | screen /dev/ttyUSB0 115200` or `picocom /dev/ttyUSB0 -b115200`. | 79 | /dev/ttyUSB0 115200` or `picocom /dev/ttyUSB0 -b115200`. |
| 75 | 80 | ||
| 76 | > Sometimes you will need to press `ENTER` in `screen` or `picocom` to access | 81 | > Sometimes you will need to press `ENTER` in `screen` or `picocom` to access |
| 77 | > REPL. | 82 | > REPL. |
| @@ -83,7 +88,7 @@ When you are in REPL you can test if all is working properly following steps. | |||
| 83 | > machine.freq() | 88 | > machine.freq() |
| 84 | ``` | 89 | ``` |
| 85 | 90 | ||
| 86 | This should output a number representing a frequency of the CPU (mine was | 91 | This should output a number representing a frequency of the CPU (mine was |
| 87 | `80000000`). | 92 | `80000000`). |
| 88 | 93 | ||
| 89 | When you are in `screen` or `picocom` these can help you a bit. | 94 | When you are in `screen` or `picocom` these can help you a bit. |
| @@ -130,7 +135,7 @@ ampy --delay 2 --port /dev/ttyUSB0 cat boot.py | |||
| 130 | 135 | ||
| 131 | ### rshell | 136 | ### rshell |
| 132 | 137 | ||
| 133 | Even though `ampy` is a cool tool I opted with `rshell` in the end since it's | 138 | Even though `ampy` is a cool tool I opted with `rshell` in the end since it's |
| 134 | much more polished and feature rich. | 139 | much more polished and feature rich. |
| 135 | 140 | ||
| 136 | ```bash | 141 | ```bash |
| @@ -144,9 +149,9 @@ Now that `rshell` is installed we can connect to the board. | |||
| 144 | rshell --buffer-size=30 -p /dev/ttyUSB0 -a | 149 | rshell --buffer-size=30 -p /dev/ttyUSB0 -a |
| 145 | ``` | 150 | ``` |
| 146 | 151 | ||
| 147 | This will open a shell inside bash and from here you can execute multiple | 152 | This will open a shell inside bash and from here you can execute multiple |
| 148 | commands. You can check what is supported with `help` once you are inside of | 153 | commands. You can check what is supported with `help` once you are inside of a |
| 149 | a shell. | 154 | shell. |
| 150 | 155 | ||
| 151 | ```bash | 156 | ```bash |
| 152 | m@turing ~/Junk/esp8266-test | 157 | m@turing ~/Junk/esp8266-test |
| @@ -177,8 +182,8 @@ Use Control-D (or the exit command) to exit rshell. | |||
| 177 | 182 | ||
| 178 | #### Moving files to flash | 183 | #### Moving files to flash |
| 179 | 184 | ||
| 180 | To avoid copying files all the time I used `rsync` function from the | 185 | To avoid copying files all the time I used `rsync` function from the inside of |
| 181 | inside of `rshell`. | 186 | `rshell`. |
| 182 | 187 | ||
| 183 | ```bash | 188 | ```bash |
| 184 | rsync . /pyboard | 189 | rsync . /pyboard |
| @@ -186,11 +191,11 @@ rsync . /pyboard | |||
| 186 | 191 | ||
| 187 | #### Executing scripts | 192 | #### Executing scripts |
| 188 | 193 | ||
| 189 | It is a pain to continuously reboot the device to trigger `/pyboard/boot.py` | 194 | It is a pain to continuously reboot the device to trigger `/pyboard/boot.py` and |
| 190 | and there is a better way of testing local scripts on remote device. | 195 | there is a better way of testing local scripts on remote device. |
| 191 | 196 | ||
| 192 | Lets assume we have `src/freq.py` file that displays CPU frequency of a | 197 | Lets assume we have `src/freq.py` file that displays CPU frequency of a remote |
| 193 | remote device. | 198 | device. |
| 194 | 199 | ||
| 195 | ```py | 200 | ```py |
| 196 | # src/freq.py | 201 | # src/freq.py |
| @@ -218,4 +223,3 @@ repl | |||
| 218 | 223 | ||
| 219 | - https://randomnerdtutorials.com/getting-started-micropython-esp32-esp8266/ | 224 | - https://randomnerdtutorials.com/getting-started-micropython-esp32-esp8266/ |
| 220 | - http://docs.micropython.org/en/latest/esp8266/quickref.html | 225 | - http://docs.micropython.org/en/latest/esp8266/quickref.html |
| 221 | |||
diff --git a/content/posts/2020-09-08-bind-warning-on-login.md b/content/posts/2020-09-08-bind-warning-on-login.md index d5d725e..113c67b 100644 --- a/content/posts/2020-09-08-bind-warning-on-login.md +++ b/content/posts/2020-09-08-bind-warning-on-login.md | |||
| @@ -5,19 +5,18 @@ date: 2020-09-08T12:00:00+02:00 | |||
| 5 | draft: false | 5 | draft: false |
| 6 | --- | 6 | --- |
| 7 | 7 | ||
| 8 | Recently I moved back to [bash](https://www.gnu.org/software/bash/) as my | 8 | Recently I moved back to [bash](https://www.gnu.org/software/bash/) as my |
| 9 | default shell. I was previously using [fish](https://fishshell.com/) and got | 9 | default shell. I was previously using [fish](https://fishshell.com/) and got |
| 10 | used to the cool features it has. But, regardless of that, I wanted to move to | 10 | used to the cool features it has. But, regardless of that, I wanted to move to a |
| 11 | a more standard shell because I was hopping back and forth with exporting | 11 | more standard shell because I was hopping back and forth with exporting |
| 12 | variables and stuff like that which got pretty annoying. | 12 | variables and stuff like that which got pretty annoying. |
| 13 | 13 | ||
| 14 | So I embarked on a mission to make [bash](https://www.gnu.org/software/bash/) | 14 | So I embarked on a mission to make [bash](https://www.gnu.org/software/bash/) |
| 15 | more like [fish](https://fishshell.com/) and in the process found that I really | 15 | more like [fish](https://fishshell.com/) and in the process found that I really |
| 16 | missed autosuggest with TAB on changing directories. | 16 | missed autosuggest with TAB on changing directories. |
| 17 | 17 | ||
| 18 | I found a nice alternative that emulates [zsh](http://zsh.sourceforge.net/) | 18 | I found a nice alternative that emulates [zsh](http://zsh.sourceforge.net/) like |
| 19 | like autosuggestion and autocomplete so I added the following to my `.bashrc` | 19 | autosuggestion and autocomplete so I added the following to my `.bashrc` file. |
| 20 | file. | ||
| 21 | 20 | ||
| 22 | ```bash | 21 | ```bash |
| 23 | bind "TAB:menu-complete" | 22 | bind "TAB:menu-complete" |
| @@ -27,15 +26,16 @@ bind "set menu-complete-display-prefix on" | |||
| 27 | bind '"\e[Z":menu-complete-backward' | 26 | bind '"\e[Z":menu-complete-backward' |
| 28 | ``` | 27 | ``` |
| 29 | 28 | ||
| 30 | I haven't noticed anything wrong with this and all was working fine until I | 29 | I haven't noticed anything wrong with this and all was working fine until I |
| 31 | restarted my machine and then I got this error. | 30 | restarted my machine and then I got this error. |
| 32 | 31 | ||
| 33 |  | 32 |  |
| 34 | 33 | ||
| 35 | When I pressed OK, I got into the [Gnome shell](https://wiki.gnome.org/Projects/GnomeShell) | 34 | When I pressed OK, I got into the [Gnome |
| 36 | and all was working fine, but the error was still bugging me. I started looking | 35 | shell](https://wiki.gnome.org/Projects/GnomeShell) and all was working fine, but |
| 37 | for the reason why this is happening and found a solution to this error on | 36 | the error was still bugging me. I started looking for the reason why this is |
| 38 | [Remote SSH Commands - bash bind warning: line editing not enabled](https://superuser.com/a/892682). | 37 | happening and found a solution to this error on [Remote SSH Commands - bash bind |
| 38 | warning: line editing not enabled](https://superuser.com/a/892682). | ||
| 39 | 39 | ||
| 40 | So I added a simple `if [ -t 1 ]` around `bind` statements to avoid running | 40 | So I added a simple `if [ -t 1 ]` around `bind` statements to avoid running |
| 41 | commands that presume the session is interactive when it isn't. | 41 | commands that presume the session is interactive when it isn't. |
| @@ -51,4 +51,3 @@ fi | |||
| 51 | ``` | 51 | ``` |
| 52 | 52 | ||
| 53 | After logging out and back in the problem was gone. | 53 | After logging out and back in the problem was gone. |
| 54 | |||
diff --git a/content/posts/2020-09-09-digitalocean-sync.md b/content/posts/2020-09-09-digitalocean-sync.md index 2eeea2e..aa3cce4 100644 --- a/content/posts/2020-09-09-digitalocean-sync.md +++ b/content/posts/2020-09-09-digitalocean-sync.md | |||
| @@ -5,25 +5,25 @@ date: 2020-09-09T12:00:00+02:00 | |||
| 5 | draft: false | 5 | draft: false |
| 6 | --- | 6 | --- |
| 7 | 7 | ||
| 8 | I've been using [Dropbox](https://www.dropbox.com/) for probably **10+ years** | 8 | I've been using [Dropbox](https://www.dropbox.com/) for probably **10+ years** |
| 9 | now and I-ve became so used to it that it runs in the background that I don't | 9 | now and I-ve became so used to it that it runs in the background that I don't |
| 10 | even imagine a world without it. But it's not without problems. | 10 | even imagine a world without it. But it's not without problems. |
| 11 | 11 | ||
| 12 | At first I had problems with `.venv` environments for Python and the only | 12 | At first I had problems with `.venv` environments for Python and the only |
| 13 | solution for excluding synchronization for this folder was to manually exclude | 13 | solution for excluding synchronization for this folder was to manually exclude a |
| 14 | a specific folder which is not really scalable. FYI, my whole project folder is | 14 | specific folder which is not really scalable. FYI, my whole project folder is |
| 15 | synced on [Dropbox](https://www.dropbox.com/). This of course introduced a lot | 15 | synced on [Dropbox](https://www.dropbox.com/). This of course introduced a lot |
| 16 | of syncing of files and folders that are not needed or even break things on | 16 | of syncing of files and folders that are not needed or even break things on |
| 17 | other machines. In the case of **Python**, I couldn't use that on my second | 17 | other machines. In the case of **Python**, I couldn't use that on my second |
| 18 | machine. I needed to delete `.venv` folder and pip it again which synced files | 18 | machine. I needed to delete `.venv` folder and pip it again which synced files |
| 19 | again to the main machine. This was very frustrating. **Nodejs** handles this | 19 | again to the main machine. This was very frustrating. **Nodejs** handles this |
| 20 | much nicer and I can just run the scripts without deleting `node_modules` again | 20 | much nicer and I can just run the scripts without deleting `node_modules` again |
| 21 | and reinstalling. However, `node_modules` is a beast of its own. It creates so | 21 | and reinstalling. However, `node_modules` is a beast of its own. It creates so |
| 22 | many files that OS has a problem counting them when you check the folder | 22 | many files that OS has a problem counting them when you check the folder |
| 23 | contents for size. | 23 | contents for size. |
| 24 | 24 | ||
| 25 | I wanted something similar to Dropbox. I could without the instant syncing | 25 | I wanted something similar to Dropbox. I could without the instant syncing but |
| 26 | but it would need to be fast and had the option for me to exclude folders like | 26 | it would need to be fast and had the option for me to exclude folders like |
| 27 | `node_modules, .venv, .git` and folders like that. | 27 | `node_modules, .venv, .git` and folders like that. |
| 28 | 28 | ||
| 29 | I went on a hunt for an alternative to [Dropbox](https://www.dropbox.com/) | 29 | I went on a hunt for an alternative to [Dropbox](https://www.dropbox.com/) |
| @@ -33,48 +33,51 @@ and found: | |||
| 33 | - [Sync.com](https://sync.com) | 33 | - [Sync.com](https://sync.com) |
| 34 | - [Box](https://www.box.com/) | 34 | - [Box](https://www.box.com/) |
| 35 | 35 | ||
| 36 | You know, the usual list of suspects. I didn't include [Google drive](https://drive.google.com) | 36 | You know, the usual list of suspects. I didn't include [Google |
| 37 | or [One drive](https://onedrive.live.com/) since they are even more draconian | 37 | drive](https://drive.google.com) or [One drive](https://onedrive.live.com/) |
| 38 | than Dropbox. | 38 | since they are even more draconian than Dropbox. |
| 39 | 39 | ||
| 40 | > All this does not stem from me being paranoid but recently these companies | 40 | > All this does not stem from me being paranoid but recently these companies |
| 41 | > have became more and more aggressive and they keep violating our privacy when | 41 | > have became more and more aggressive and they keep violating our privacy when |
| 42 | > they share our data with 3rd party services. It is getting out of control. | 42 | > they share our data with 3rd party services. It is getting out of control. |
| 43 | 43 | ||
| 44 | So, my main problem was still there. No way of excluding a specific folder | 44 | So, my main problem was still there. No way of excluding a specific folder from |
| 45 | from syncing. And before we go into "*But you have git, isn't that enough?*", | 45 | syncing. And before we go into "*But you have git, isn't that enough?*", I must |
| 46 | I must say, that many of the files (PDFs, spreadsheets, etc) I have in a `git` | 46 | say, that many of the files (PDFs, spreadsheets, etc) I have in a `git` repo |
| 47 | repo don't get pushed upstream to Git and I still want to have them synced | 47 | don't get pushed upstream to Git and I still want to have them synced across my |
| 48 | across my computers. | 48 | computers. |
| 49 | 49 | ||
| 50 | I initially wanted to use [rsync](https://linux.die.net/man/1/rsync) but I | 50 | I initially wanted to use [rsync](https://linux.die.net/man/1/rsync) but I would |
| 51 | would need to then have a remote VPS or transfer between my computers directly. | 51 | need to then have a remote VPS or transfer between my computers directly. I |
| 52 | I wanted a solution where all my files could be accessible to me without my | 52 | wanted a solution where all my files could be accessible to me without my |
| 53 | machine. | 53 | machine. |
| 54 | 54 | ||
| 55 | > **WARNING: This solution will cost you money!** DigitalOcean Spaces are $5 | 55 | > **WARNING: This solution will cost you money!** DigitalOcean Spaces are $5 per |
| 56 | per month and there are some bandwidth limitations and if you go beyond that | 56 | month and there are some bandwidth limitations and if you go beyond that you get |
| 57 | you get billed additionally. | 57 | billed additionally. |
| 58 | 58 | ||
| 59 | Then I remembered that I could use something like [S3](https://en.wikipedia.org/wiki/Amazon_S3) | 59 | Then I remembered that I could use something like |
| 60 | since it has versioning and is fully managed. I didn't want to go down the AWS | 60 | [S3](https://en.wikipedia.org/wiki/Amazon_S3) since it has versioning and is |
| 61 | rabbit hole with this so I choose [DigitalOcean Spaces](https://www.digitalocean.com/products/spaces/). | 61 | fully managed. I didn't want to go down the AWS rabbit hole with this so I |
| 62 | choose [DigitalOcean Spaces](https://www.digitalocean.com/products/spaces/). | ||
| 62 | 63 | ||
| 63 | Then I needed a command-line tool to sync between source and target. I found | 64 | Then I needed a command-line tool to sync between source and target. I found |
| 64 | this nice tool [s3cmd](https://s3tools.org/s3cmd) and it is in the Ubuntu | 65 | this nice tool [s3cmd](https://s3tools.org/s3cmd) and it is in the Ubuntu |
| 65 | repositories. | 66 | repositories. |
| 66 | 67 | ||
| 67 | ```bash | 68 | ```bash |
| 68 | sudo apt install s3cmd | 69 | sudo apt install s3cmd |
| 69 | ``` | 70 | ``` |
| 70 | 71 | ||
| 71 | After installation will I create a new Space bucket on DigitalOcean. Remember | 72 | After installation will I create a new Space bucket on DigitalOcean. Remember |
| 72 | the zone you will choose because you will need it when you will configure `s3cmd`. | 73 | the zone you will choose because you will need it when you will configure |
| 74 | `s3cmd`. | ||
| 73 | 75 | ||
| 74 | Then I visited [Digitalocean Applications & API](https://cloud.digitalocean.com/account/api/tokens) | 76 | Then I visited [Digitalocean Applications & |
| 75 | and generated **Spaces access keys**. Save both key and secret somewhere safe | 77 | API](https://cloud.digitalocean.com/account/api/tokens) and generated **Spaces |
| 76 | because when you will leave the page secret will not be available anymore to | 78 | access keys**. Save both key and secret somewhere safe because when you will |
| 77 | you and you will need to re-generate it. | 79 | leave the page secret will not be available anymore to you and you will need to |
| 80 | re-generate it. | ||
| 78 | 81 | ||
| 79 | ```bash | 82 | ```bash |
| 80 | # enter your key and secret and correct endpoint | 83 | # enter your key and secret and correct endpoint |
| @@ -101,10 +104,8 @@ When syncing int he other direction you will need to change the order of the | |||
| 101 | I am planning to implement some sort of a `.ignore` file that will enable me to | 104 | I am planning to implement some sort of a `.ignore` file that will enable me to |
| 102 | have a project-specific exclude options. | 105 | have a project-specific exclude options. |
| 103 | 106 | ||
| 104 | I am currently running this every hour as a cronjob which is perfectly fine | 107 | I am currently running this every hour as a cronjob which is perfectly fine for |
| 105 | for now when I am testing how this whole thing works and how it all will turn | 108 | now when I am testing how this whole thing works and how it all will turn out. |
| 106 | out. | ||
| 107 | 109 | ||
| 108 | I have also created a small Gnome extension which is still very unstable, but | 110 | I have also created a small Gnome extension which is still very unstable, but |
| 109 | when/if this whole experiment pays of I will share on Github. | 111 | when/if this whole experiment pays of I will share on Github. |
| 110 | |||
diff --git a/content/posts/2021-01-24-replacing-dropbox-with-s3.md b/content/posts/2021-01-24-replacing-dropbox-with-s3.md index 0253368..4c6b33e 100644 --- a/content/posts/2021-01-24-replacing-dropbox-with-s3.md +++ b/content/posts/2021-01-24-replacing-dropbox-with-s3.md | |||
| @@ -5,27 +5,30 @@ date: 2021-01-24T12:00:00+02:00 | |||
| 5 | draft: false | 5 | draft: false |
| 6 | --- | 6 | --- |
| 7 | 7 | ||
| 8 | A few months ago I experimented with DigitalOcean spaces as my backup solution | 8 | A few months ago I experimented with DigitalOcean spaces as my backup solution |
| 9 | that could [replace Dropbox eventually](/digitalocean-spaces-to-sync-between-computers.html). | 9 | that could [replace Dropbox |
| 10 | That solution worked quite nicely, and I was amazed how smashing together a | 10 | eventually](/digitalocean-spaces-to-sync-between-computers.html). That solution |
| 11 | couple of existing solutions would work this fine. | 11 | worked quite nicely, and I was amazed how smashing together a couple of existing |
| 12 | 12 | solutions would work this fine. | |
| 13 | I have been running that solution in the background for a couple of months now | 13 | |
| 14 | and kind of forgot about it. But recent developments around deplatforming and | 14 | I have been running that solution in the background for a couple of months now |
| 15 | having us people hostages of technology and big companies speed up my goals to | 15 | and kind of forgot about it. But recent developments around deplatforming and |
| 16 | become less dependent on [Google](https://edition.cnn.com/2020/12/17/tech/google-antitrust-lawsuit/index.html), | 16 | having us people hostages of technology and big companies speed up my goals to |
| 17 | [Dropbox](https://www.pcworld.com/article/2048680/dropbox-takes-a-peek-at-files.html) | 17 | become less dependent on |
| 18 | [Google](https://edition.cnn.com/2020/12/17/tech/google-antitrust-lawsuit/index.html), | ||
| 19 | [Dropbox](https://www.pcworld.com/article/2048680/dropbox-takes-a-peek-at-files.html) | ||
| 18 | etc and take back some control. | 20 | etc and take back some control. |
| 19 | 21 | ||
| 20 | I am not a conspiracy theory nut, but to be honest, what these companies are | 22 | I am not a conspiracy theory nut, but to be honest, what these companies are |
| 21 | doing lately is out of control. It is a matter of principle at this point. I | 23 | doing lately is out of control. It is a matter of principle at this point. I |
| 22 | have almost completely degoogled my life all the way from ditching Gmail, | 24 | have almost completely degoogled my life all the way from ditching Gmail, |
| 23 | YouTube and most of the services surrounding Google. And I must tell you, I | 25 | YouTube and most of the services surrounding Google. And I must tell you, I feel |
| 24 | feel so good. I haven't felt this way for a long time. | 26 | so good. I haven't felt this way for a long time. |
| 25 | 27 | ||
| 26 | **Anyways. Let's get to the meat of things.** | 28 | **Anyways. Let's get to the meat of things.** |
| 27 | 29 | ||
| 28 | Before you continue you should read my post about [syncing to Dropbox](/digitalocean-spaces-to-sync-between-computers.html). | 30 | Before you continue you should read my post about [syncing to |
| 31 | Dropbox](/digitalocean-spaces-to-sync-between-computers.html). | ||
| 29 | 32 | ||
| 30 | > Also to note, I am using Linux on my machine with Gnome desktop environment. | 33 | > Also to note, I am using Linux on my machine with Gnome desktop environment. |
| 31 | This should work on MacOS too. To use this on Windows I suggest using | 34 | This should work on MacOS too. To use this on Windows I suggest using |
| @@ -34,7 +37,7 @@ or [Cygwin](https://www.cygwin.com/). | |||
| 34 | 37 | ||
| 35 | ## Folder structure | 38 | ## Folder structure |
| 36 | 39 | ||
| 37 | I liked structure from Dropbox. One folder where everything is located and | 40 | I liked structure from Dropbox. One folder where everything is located and |
| 38 | synced. So, that's why adopted this also for my sync setup. | 41 | synced. So, that's why adopted this also for my sync setup. |
| 39 | 42 | ||
| 40 | ```go | 43 | ```go |
| @@ -45,11 +48,10 @@ synced. So, that's why adopted this also for my sync setup. | |||
| 45 | ↳ projects | 48 | ↳ projects |
| 46 | ``` | 49 | ``` |
| 47 | 50 | ||
| 48 | All of my code is located in `~/Vault/projects` folder. And most of the | 51 | All of my code is located in `~/Vault/projects` folder. And most of the projects |
| 49 | projects are Git repositories. I do not use this sync method for backup per | 52 | are Git repositories. I do not use this sync method for backup per see but in |
| 50 | see but in case I reinstall my machine I can easily recreate all the important | 53 | case I reinstall my machine I can easily recreate all the important folder |
| 51 | folder structure with one quick command. No external drives needed that can | 54 | structure with one quick command. No external drives needed that can fail etc. |
| 52 | fail etc. | ||
| 53 | 55 | ||
| 54 | ## Sync script | 56 | ## Sync script |
| 55 | 57 | ||
| @@ -86,8 +88,8 @@ notify-send \ | |||
| 86 | "Vault sync succeded at `date +"%D %T"`" | 88 | "Vault sync succeded at `date +"%D %T"`" |
| 87 | ``` | 89 | ``` |
| 88 | 90 | ||
| 89 | This script also backups some of the dotfiles I use and sends notification to | 91 | This script also backups some of the dotfiles I use and sends notification to |
| 90 | Gnome notification center. It is a straightforward solution. Nothing special | 92 | Gnome notification center. It is a straightforward solution. Nothing special |
| 91 | going on. | 93 | going on. |
| 92 | 94 | ||
| 93 | > One obvious benefit of this is that I can omit syncing Node's `node_modules` | 95 | > One obvious benefit of this is that I can omit syncing Node's `node_modules` |
| @@ -99,14 +101,13 @@ You can use this script in a combination with [Cron](https://en.wikipedia.org/wi | |||
| 99 | 0 2 * * * sh ~/Vault/bin/vault-backup.sh | 101 | 0 2 * * * sh ~/Vault/bin/vault-backup.sh |
| 100 | ``` | 102 | ``` |
| 101 | 103 | ||
| 102 | When you start syncing your local stuff with a remote server you can review | 104 | When you start syncing your local stuff with a remote server you can review your |
| 103 | your items on DigitalOcean. | 105 | items on DigitalOcean. |
| 104 | 106 | ||
| 105 |  | 107 |  |
| 106 | 108 | ||
| 107 | I have been using this script now for quite some time, and it's working | 109 | I have been using this script now for quite some time, and it's working |
| 108 | flawlessly. I also uninstalled Dropbox and stopped using it completely. | 110 | flawlessly. I also uninstalled Dropbox and stopped using it completely. |
| 109 | 111 | ||
| 110 | All I need to do is write a Bash script that does the reverse and downloads | 112 | All I need to do is write a Bash script that does the reverse and downloads from |
| 111 | from remote server to local folder. This could be another post. | 113 | remote server to local folder. This could be another post. |
| 112 | |||
diff --git a/content/posts/2021-01-25-goaccess.md b/content/posts/2021-01-25-goaccess.md index efbd175..1b6a330 100644 --- a/content/posts/2021-01-25-goaccess.md +++ b/content/posts/2021-01-25-goaccess.md | |||
| @@ -7,16 +7,16 @@ draft: false | |||
| 7 | 7 | ||
| 8 | ## Introduction | 8 | ## Introduction |
| 9 | 9 | ||
| 10 | I know! You cannot simply replace Google Analytics with parsing access logs and | 10 | I know! You cannot simply replace Google Analytics with parsing access logs and |
| 11 | displaying a couple of charts. But to be honest, I actually never used Google | 11 | displaying a couple of charts. But to be honest, I actually never used Google |
| 12 | Analytics to the fullest extent and was usually interested in seeing page | 12 | Analytics to the fullest extent and was usually interested in seeing page hits |
| 13 | hits and which pages were visited most often. | 13 | and which pages were visited most often. |
| 14 | 14 | ||
| 15 | I recently moved my blog from Firebase to a VPS and also decided to remove | 15 | I recently moved my blog from Firebase to a VPS and also decided to remove |
| 16 | Google Analytics tracking code from the site since its quite malicious and | 16 | Google Analytics tracking code from the site since its quite malicious and |
| 17 | tracks users across other pages also and is creating a profile of a user, and | 17 | tracks users across other pages also and is creating a profile of a user, and |
| 18 | I've had it. But I also need some insight of what is happening on a server | 18 | I've had it. But I also need some insight of what is happening on a server and |
| 19 | and which content is being read the most etc. | 19 | which content is being read the most etc. |
| 20 | 20 | ||
| 21 | I have looked at many existing solutions like: | 21 | I have looked at many existing solutions like: |
| 22 | 22 | ||
| @@ -24,18 +24,18 @@ I have looked at many existing solutions like: | |||
| 24 | - [Freshlytics](https://github.com/sheshbabu/freshlytics) | 24 | - [Freshlytics](https://github.com/sheshbabu/freshlytics) |
| 25 | - [Matomo](https://matomo.org/) | 25 | - [Matomo](https://matomo.org/) |
| 26 | 26 | ||
| 27 | But the more I looked at them the more I noticed that I am replacing one evil | 27 | But the more I looked at them the more I noticed that I am replacing one evil |
| 28 | with another one. Don't get me wrong. Some of these solutions are absolutely | 28 | with another one. Don't get me wrong. Some of these solutions are absolutely |
| 29 | fantastic but would require installation of databases and something like PHP | 29 | fantastic but would require installation of databases and something like PHP or |
| 30 | or Node. And I was not ready to put those things on my fresh server. Also | 30 | Node. And I was not ready to put those things on my fresh server. Also having |
| 31 | having Docker installed is out of the question. | 31 | Docker installed is out of the question. |
| 32 | 32 | ||
| 33 | ## Opting for log parsing | 33 | ## Opting for log parsing |
| 34 | 34 | ||
| 35 | So, I defaulted to parsing already existing logs and generating HTML reports | 35 | So, I defaulted to parsing already existing logs and generating HTML reports |
| 36 | from this data. | 36 | from this data. |
| 37 | 37 | ||
| 38 | I found this amazing software [GoAccess](https://goaccess.io/) which provides | 38 | I found this amazing software [GoAccess](https://goaccess.io/) which provides |
| 39 | all the functionalities I need, and it's a single binary. Written in Go. | 39 | all the functionalities I need, and it's a single binary. Written in Go. |
| 40 | 40 | ||
| 41 | GoAccess can be used in two different modes. | 41 | GoAccess can be used in two different modes. |
| @@ -46,15 +46,16 @@ GoAccess can be used in two different modes. | |||
| 46 |  | 46 |  |
| 47 | <center><i>Running in a browser</i></center> | 47 | <center><i>Running in a browser</i></center> |
| 48 | 48 | ||
| 49 | I, however, need this to run in a browser. So, the second option is the way | 49 | I, however, need this to run in a browser. So, the second option is the way to |
| 50 | to go. The Idea is to periodically run cronjob and export this report into a | 50 | go. The Idea is to periodically run cronjob and export this report into a folder |
| 51 | folder that gets then server by Nginx behind a Basic authentication. | 51 | that gets then server by Nginx behind a Basic authentication. |
| 52 | 52 | ||
| 53 | ## Getting Nginx ready | 53 | ## Getting Nginx ready |
| 54 | 54 | ||
| 55 | I choose Ubuntu on [DigitalOcean](https://www.digitalocean.com/). First I | 55 | I choose Ubuntu on [DigitalOcean](https://www.digitalocean.com/). First I |
| 56 | installed [Nginx](https://nginx.org/en/), and [Letsencrypt](https://letsencrypt.org/getting-started/) | 56 | installed [Nginx](https://nginx.org/en/), and |
| 57 | certbot and all the necessary dependencies. | 57 | [Letsencrypt](https://letsencrypt.org/getting-started/) certbot and all the |
| 58 | necessary dependencies. | ||
| 58 | 59 | ||
| 59 | ```sh | 60 | ```sh |
| 60 | # log in as root user | 61 | # log in as root user |
| @@ -90,26 +91,25 @@ server { | |||
| 90 | } | 91 | } |
| 91 | ``` | 92 | ``` |
| 92 | 93 | ||
| 93 | Now we check if the configuration is ok. We can do this with `nginx -t`. If | 94 | Now we check if the configuration is ok. We can do this with `nginx -t`. If all |
| 94 | all is ok, we can restart Nginx with `service nginx restart`. | 95 | is ok, we can restart Nginx with `service nginx restart`. |
| 95 | 96 | ||
| 96 | After all that you should add A record for this domain that points to IP of | 97 | After all that you should add A record for this domain that points to IP of a |
| 97 | a droplet. | 98 | droplet. |
| 98 | 99 | ||
| 99 | Before enabling SSL you should test if DNS records have propagated with | 100 | Before enabling SSL you should test if DNS records have propagated with `curl |
| 100 | `curl stats.domain.com`. | 101 | stats.domain.com`. |
| 101 | 102 | ||
| 102 | Now, it's time to provision TLS certificate. To achieve this, you execute command | 103 | Now, it's time to provision TLS certificate. To achieve this, you execute |
| 103 | `certbot --nginx`. Follow the wizard and when you are asked about redirection | 104 | command `certbot --nginx`. Follow the wizard and when you are asked about |
| 104 | always choose 2 (always redirect to HTTPS). | 105 | redirection always choose 2 (always redirect to HTTPS). |
| 105 | 106 | ||
| 106 | When this is done you can visit https://stats.domain.com and you should get 404 | 107 | When this is done you can visit https://stats.domain.com and you should get 404 |
| 107 | not found error which is correct. | 108 | not found error which is correct. |
| 108 | 109 | ||
| 109 | |||
| 110 | ## Getting GoAccess ready | 110 | ## Getting GoAccess ready |
| 111 | 111 | ||
| 112 | If you are using Debian like system GoAccess should be available in repository. | 112 | If you are using Debian like system GoAccess should be available in repository. |
| 113 | Otherwise refer to the official website. | 113 | Otherwise refer to the official website. |
| 114 | 114 | ||
| 115 | ```sh | 115 | ```sh |
| @@ -148,19 +148,19 @@ goaccess \ | |||
| 148 | rm /var/log/nginx/access-all.log | 148 | rm /var/log/nginx/access-all.log |
| 149 | ``` | 149 | ``` |
| 150 | 150 | ||
| 151 | Because after a while nginx creates multiple files with access logs we use | 151 | Because after a while nginx creates multiple files with access logs we use |
| 152 | [`zcat`](https://linux.die.net/man/1/zcat) to extract Gziped contents and | 152 | [`zcat`](https://linux.die.net/man/1/zcat) to extract Gziped contents and create |
| 153 | create a file that has all the access logs. After this file is used we | 153 | a file that has all the access logs. After this file is used we delete it. |
| 154 | delete it. | ||
| 155 | 154 | ||
| 156 | If you want to exclude your home IP's result look at the `--exclude-ip` option | 155 | If you want to exclude your home IP's result look at the `--exclude-ip` option |
| 157 | in script and instead of `0.0.0.0` add your own home IP address. You can find | 156 | in script and instead of `0.0.0.0` add your own home IP address. You can find |
| 158 | your home IP by executing `curl ifconfig.me` from your local machine and NOT | 157 | your home IP by executing `curl ifconfig.me` from your local machine and NOT |
| 159 | from the droplet. | 158 | from the droplet. |
| 160 | 159 | ||
| 161 | Test the script by executing `sh /var/www/html/stats.domain.com/generate-stats.sh` | 160 | Test the script by executing `sh |
| 162 | and then checking `https://stats.domain.com`. If you can see stats instead of | 161 | /var/www/html/stats.domain.com/generate-stats.sh` and then checking |
| 163 | 404 than you are set. | 162 | `https://stats.domain.com`. If you can see stats instead of 404 than you are |
| 163 | set. | ||
| 164 | 164 | ||
| 165 | It's time to add this script to cron with `cron -e`. | 165 | It's time to add this script to cron with `cron -e`. |
| 166 | 166 | ||
| @@ -170,16 +170,17 @@ It's time to add this script to cron with `cron -e`. | |||
| 170 | 170 | ||
| 171 | ## Securing with Basic authentication | 171 | ## Securing with Basic authentication |
| 172 | 172 | ||
| 173 | You probably don't want stats to be publicly available, so we should create a | 173 | You probably don't want stats to be publicly available, so we should create a |
| 174 | user and a password for Basic authentication. | 174 | user and a password for Basic authentication. |
| 175 | 175 | ||
| 176 | First we create a password for a user `stats` with `htpasswd -c /etc/nginx/.htpasswd stats`. | 176 | First we create a password for a user `stats` with `htpasswd -c /etc/nginx/.htpasswd stats`. |
| 177 | 177 | ||
| 178 | Now we update config file with `nano /etc/nginx/sites-available/stats.domain.com`. | 178 | Now we update config file with `nano |
| 179 | You probably noticed that the file looks a bit different from before. This is | 179 | /etc/nginx/sites-available/stats.domain.com`. You probably noticed that the |
| 180 | because `certbot` added additional rules for SSL. | 180 | file looks a bit different from before. This is because `certbot` added |
| 181 | additional rules for SSL. | ||
| 181 | 182 | ||
| 182 | Your location portion the config file should now look like. You should add | 183 | Your location portion the config file should now look like. You should add |
| 183 | `auth_basic` and `auth_basic_user_file` lines to the file. | 184 | `auth_basic` and `auth_basic_user_file` lines to the file. |
| 184 | 185 | ||
| 185 | ```nginx | 186 | ```nginx |
| @@ -190,12 +191,12 @@ location / { | |||
| 190 | } | 191 | } |
| 191 | ``` | 192 | ``` |
| 192 | 193 | ||
| 193 | Test if config is still ok with `nginx -t` and if it is you can restart | 194 | Test if config is still ok with `nginx -t` and if it is you can restart Nginx |
| 194 | Nginx with `service nginx restart`. | 195 | with `service nginx restart`. |
| 195 | 196 | ||
| 196 | If you now visit `https://stats.domain.com` you should be prompted for username | 197 | If you now visit `https://stats.domain.com` you should be prompted for username |
| 197 | and password. If not, try reopening your browser. | 198 | and password. If not, try reopening your browser. |
| 198 | 199 | ||
| 199 | That is all. You now have analytics for your server that gets refreshed every | 200 | That is all. You now have analytics for your server that gets refreshed every 10 |
| 200 | 10 minutes. | 201 | minutes. |
| 201 | 202 | ||
diff --git a/content/posts/2021-06-26-simple-world-clock.md b/content/posts/2021-06-26-simple-world-clock.md index f42af11..ed248dd 100644 --- a/content/posts/2021-06-26-simple-world-clock.md +++ b/content/posts/2021-06-26-simple-world-clock.md | |||
| @@ -5,29 +5,32 @@ date: 2021-06-26T12:00:00+02:00 | |||
| 5 | draft: false | 5 | draft: false |
| 6 | --- | 6 | --- |
| 7 | 7 | ||
| 8 | Our team is spread across the world, from the USA all the way to Australia, | 8 | Our team is spread across the world, from the USA all the way to Australia, so |
| 9 | so having some sort of world clock makes sense. | 9 | having some sort of world clock makes sense. |
| 10 | 10 | ||
| 11 | Currently, I am using an extension for Gnome called | 11 | Currently, I am using an extension for Gnome called [Timezone |
| 12 | [Timezone extension](https://extensions.gnome.org/extension/2657/timezones-extension/), | 12 | extension](https://extensions.gnome.org/extension/2657/timezones-extension/), |
| 13 | and it serves the purpose quite well. | 13 | and it serves the purpose quite well. |
| 14 | 14 | ||
| 15 | But I also have a bunch of electronics that I bought through the time, and I | 15 | But I also have a bunch of electronics that I bought through the time, and I am |
| 16 | am not using any of them, and it's time to stop hording this stuff and use it | 16 | not using any of them, and it's time to stop hording this stuff and use it in a |
| 17 | in a project. | 17 | project. |
| 18 | 18 | ||
| 19 | A while ago I bought a small eInk display | 19 | A while ago I bought a small eInk display [Inky |
| 20 | [Inky pHAT](https://shop.pimoroni.com/products/inky-phat?variant=12549254217811) | 20 | pHAT](https://shop.pimoroni.com/products/inky-phat?variant=12549254217811) and I |
| 21 | and I have a bunch of [Raspberry Pi's Zero](https://www.raspberrypi.org/products/raspberry-pi-zero/) | 21 | have a bunch of [Raspberry Pi's |
| 22 | lying around that I really need to use. | 22 | Zero](https://www.raspberrypi.org/products/raspberry-pi-zero/) lying around that |
| 23 | I really need to use. | ||
| 23 | 24 | ||
| 24 |  | 25 |  |
| 25 | 26 | ||
| 26 | Since the Inky [Inky pHAT](https://shop.pimoroni.com/products/inky-phat?variant=12549254217811) | 27 | Since the Inky [Inky |
| 27 | is essentially a HAT, it can easily be added on top of the | 28 | pHAT](https://shop.pimoroni.com/products/inky-phat?variant=12549254217811) is |
| 28 | [Raspberry Pi Zero](https://www.raspberrypi.org/products/raspberry-pi-zero/). | 29 | essentially a HAT, it can easily be added on top of the [Raspberry Pi |
| 30 | Zero](https://www.raspberrypi.org/products/raspberry-pi-zero/). | ||
| 29 | 31 | ||
| 30 | First, I installed the necessary software on Raspberry Pi with `pip3 install inky`. | 32 | First, I installed the necessary software on Raspberry Pi with `pip3 install |
| 33 | inky`. | ||
| 31 | 34 | ||
| 32 | And then I created a file `clock.py` in home directory `/home/pi`. | 35 | And then I created a file `clock.py` in home directory `/home/pi`. |
| 33 | 36 | ||
| @@ -76,10 +79,11 @@ board.set_image(img) | |||
| 76 | board.show() | 79 | board.show() |
| 77 | ``` | 80 | ``` |
| 78 | 81 | ||
| 79 | And because eInk displays are rather slow to refresh and the clock requires | 82 | And because eInk displays are rather slow to refresh and the clock requires |
| 80 | refreshing only once a minute, this can be done through cronjob. | 83 | refreshing only once a minute, this can be done through cronjob. |
| 81 | 84 | ||
| 82 | Before we add this job to cron we need to make `clock.py` executable with `chmod +x clock.py`. | 85 | Before we add this job to cron we need to make `clock.py` executable with `chmod |
| 86 | +x clock.py`. | ||
| 83 | 87 | ||
| 84 | Then we add a cronjob with `crontab -e`. | 88 | Then we add a cronjob with `crontab -e`. |
| 85 | 89 | ||
| @@ -91,13 +95,13 @@ So, we end up with a result like this. | |||
| 91 | 95 | ||
| 92 |  | 96 |  |
| 93 | 97 | ||
| 94 | And for the enclosure that can be 3D printed, but I haven't yet something like | 98 | And for the enclosure that can be 3D printed, but I haven't yet something like |
| 95 | this can be used. | 99 | this can be used. |
| 96 | 100 | ||
| 97 | <iframe id="vs_iframe" src="https://www.viewstl.com/?embedded&url=https%3A%2F%2Fmitjafelicijan.com%2Fassets%2Fworld-clock%2Fenclosure.stl&color=gray&bgcolor=white&edges=no&orientation=front&noborder=no" style="border:0;margin:0;width:100%;height:400px;"></iframe> | 101 | <iframe id="vs_iframe" src="https://www.viewstl.com/?embedded&url=https%3A%2F%2Fmitjafelicijan.com%2Fassets%2Fworld-clock%2Fenclosure.stl&color=gray&bgcolor=white&edges=no&orientation=front&noborder=no" style="border:0;margin:0;width:100%;height:400px;"></iframe> |
| 98 | 102 | ||
| 99 | You can download my [STL file for the enclosure here](/assets/world-clock/enclosure.stl), | 103 | You can download my [STL file for the enclosure |
| 100 | but make sure that dimensions make sense and also opening for USB port should | 104 | here](/assets/world-clock/enclosure.stl), but make sure that dimensions make |
| 101 | be added or just use a drill and some hot glue to make it stick in the | 105 | sense and also opening for USB port should be added or just use a drill and some |
| 102 | enclosure. | 106 | hot glue to make it stick in the enclosure. |
| 103 | 107 | ||
diff --git a/content/posts/2021-07-30-from-internet-consumer-to-full-hominum-again.md b/content/posts/2021-07-30-from-internet-consumer-to-full-hominum-again.md index 27e0905..31a2ea0 100644 --- a/content/posts/2021-07-30-from-internet-consumer-to-full-hominum-again.md +++ b/content/posts/2021-07-30-from-internet-consumer-to-full-hominum-again.md | |||
| @@ -12,93 +12,91 @@ I was pleasantly surprised that the transition went so smoothly. Even better, | |||
| 12 | it brought many benefits to my life. Such as increased focus, less stress | 12 | it brought many benefits to my life. Such as increased focus, less stress |
| 13 | about trivial things, etc. | 13 | about trivial things, etc. |
| 14 | 14 | ||
| 15 | It all started with me doing small changes like unsubscribing from emails that | 15 | It all started with me doing small changes like unsubscribing from emails that I |
| 16 | I have either subscribed to by accepting terms and conditions. Or even some | 16 | have either subscribed to by accepting terms and conditions. Or even some more |
| 17 | more malicious emails that I was getting because I was on a shared mailing | 17 | malicious emails that I was getting because I was on a shared mailing list. And |
| 18 | list. And the later ones I hate the most of all. How the hell do they keep | 18 | the later ones I hate the most of all. How the hell do they keep sharing my |
| 19 | sharing my email and sending me unsolicited emails and get away with it? I | 19 | email and sending me unsolicited emails and get away with it? I have a suspicion |
| 20 | have a suspicion that these marketing people share an Excel file between them | 20 | that these marketing people share an Excel file between them and keep |
| 21 | and keep resubscribing me when they import lists into Mailchimp or similar | 21 | resubscribing me when they import lists into Mailchimp or similar software. |
| 22 | software. | ||
| 23 | 22 | ||
| 24 | It's fascinating to see how much crap you get subscribed to when you are not | 23 | It's fascinating to see how much crap you get subscribed to when you are not |
| 25 | paying attention. It got so bad that my primary Gmail address is a full of junk | 24 | paying attention. It got so bad that my primary Gmail address is a full of junk |
| 26 | and need constant monitoring and cleaning up. And because I want to have Inbox | 25 | and need constant monitoring and cleaning up. And because I want to have Inbox |
| 27 | Zero, this presents an additional problem for me. | 26 | Zero, this presents an additional problem for me. |
| 28 | 27 | ||
| 29 | The stress that email presented for me didn't occur to me for a long time. I | 28 | The stress that email presented for me didn't occur to me for a long time. I was |
| 30 | was noticing that I was unable to go through one single hour without | 29 | noticing that I was unable to go through one single hour without hysterically |
| 31 | hysterically refreshing email. And if somebody wrote me something, I needed | 30 | refreshing email. And if somebody wrote me something, I needed to see it right |
| 32 | to see it right then, even though I didn't immediately reply to it. I can | 31 | then, even though I didn't immediately reply to it. I can only describe this |
| 33 | only describe this with FOMO (fear of missing out). I have no other explanation | 32 | with FOMO (fear of missing out). I have no other explanation than that. It was |
| 34 | than that. It was crippling, and I was constantly context switching, which I | 33 | crippling, and I was constantly context switching, which I will address further |
| 35 | will address further down this post in more details. | 34 | down this post in more details. |
| 36 | 35 | ||
| 37 | This was one of the reasons why I spawned up my personal email server, and I | 36 | This was one of the reasons why I spawned up my personal email server, and I am |
| 38 | am using it now as my primary and person email. I still have Gmail as my “junk” | 37 | using it now as my primary and person email. I still have Gmail as my “junk” |
| 39 | email that I use for throw away stuff. I log in to Gmail once a week and check | 38 | email that I use for throw away stuff. I log in to Gmail once a week and check |
| 40 | if there are any important emails that I got, but apart from that, it's | 39 | if there are any important emails that I got, but apart from that, it's sitting |
| 41 | sitting dormant and collecting dust. | 40 | dormant and collecting dust. |
| 42 | 41 | ||
| 43 | The more I was watching the world loose it's self with allowing anti freedom | 42 | The more I was watching the world loose it's self with allowing anti freedom |
| 44 | things to happen to it, the more I started to realize that something has to | 43 | things to happen to it, the more I started to realize that something has to |
| 45 | change. I don't have the power to change the world. And I also don't have a | 44 | change. I don't have the power to change the world. And I also don't have a |
| 46 | grandiose opinion of myself to even think to try it. But what I can do is to | 45 | grandiose opinion of myself to even think to try it. But what I can do is to not |
| 47 | not subscribe to this consumer way of thinking. I will not be complicit in | 46 | subscribe to this consumer way of thinking. I will not be complicit in this. My |
| 48 | this. My moral and ethical stances won't allow it. So, this brings us to the | 47 | moral and ethical stances won't allow it. So, this brings us to the second part |
| 49 | second part of my journey. | 48 | of my journey. |
| 50 | 49 | ||
| 51 | I was using all these 3rd party services because I was either lazy or OK with | 50 | I was using all these 3rd party services because I was either lazy or OK with |
| 52 | the drawbacks of them. I watched these services and companies became more and | 51 | the drawbacks of them. I watched these services and companies became more and |
| 53 | more evil. It is evil if you sell your user's data in this manner. Nobody reads | ||
| 54 | privacy policies and everybody is OK with accepting them, and they pray on that | 52 | privacy policies and everybody is OK with accepting them, and they pray on that |
| 53 | more evil. It is evil if you sell your user's data in this manner. Nobody reads | ||
| 55 | flaw in human nature. I really hate the hypocrisy they manage to muster. These | 54 | flaw in human nature. I really hate the hypocrisy they manage to muster. These |
| 56 | companies prey on our laziness, and we are at fault here. Nobody else. And I | 55 | companies prey on our laziness, and we are at fault here. Nobody else. And I |
| 57 | truly understand the reasons why we rather accept and move on, and not object | 56 | truly understand the reasons why we rather accept and move on, and not object |
| 58 | and have our lives a little more difficult. They have perfected this through | 57 | and have our lives a little more difficult. They have perfected this through |
| 59 | years of small changes that make us a little more dependent on them. You could | 58 | years of small changes that make us a little more dependent on them. You could |
| 60 | not convince a person to give away all his rights and data in one day. This was | 59 | not convince a person to give away all his rights and data in one day. This was |
| 61 | gradual and slow. And it caught us all in surprise. When I really stopped and | 60 | gradual and slow. And it caught us all in surprise. When I really stopped and |
| 62 | thought about it, I felt repulsed. By really stopping and thinking about it, | 61 | thought about it, I felt repulsed. By really stopping and thinking about it, I |
| 63 | I really mean stopping and thinking about it. Thoroughly and in depth. | 62 | really mean stopping and thinking about it. Thoroughly and in depth. |
| 64 | 63 | ||
| 65 | Each step I took depleted my character a bit more. Like I was trading myself | 64 | Each step I took depleted my character a bit more. Like I was trading myself bit |
| 66 | bit by bit without understanding what it all meant. What it meant to be a full | 65 | by bit without understanding what it all meant. What it meant to be a full |
| 67 | person, not divided by all this bought attention they want from me. They don't | 66 | person, not divided by all this bought attention they want from me. They don't |
| 68 | just get your data, but they also take your attention away from you. They | 67 | just get your data, but they also take your attention away from you. They |
| 69 | scatter your and go with the divide and conquer tactic from there. And a person | 68 | scatter your and go with the divide and conquer tactic from there. And a person |
| 70 | divided is a person not fully there. Not at the moment. Not alive fully. | 69 | divided is a person not fully there. Not at the moment. Not alive fully. |
| 71 | 70 | ||
| 72 | I was unable to form long thoughts. Well, I thought I was. But now that I see | 71 | I was unable to form long thoughts. Well, I thought I was. But now that I see |
| 73 | what being a full person is again, I can see that I was not at my 100% back | 72 | what being a full person is again, I can see that I was not at my 100% back |
| 74 | then. | 73 | then. |
| 75 | 74 | ||
| 76 | A revolt was inevitable. There was no other way of continuing my story without | 75 | A revolt was inevitable. There was no other way of continuing my story without |
| 77 | it. Without taking back my attention, my thoughts, my time, and my privacy, | 76 | it. Without taking back my attention, my thoughts, my time, and my privacy, |
| 78 | regardless of how too late it maybe is. | 77 | regardless of how too late it maybe is. |
| 79 | 78 | ||
| 80 | This has nothing to do with conspiracy theories. Even less with changing the | 79 | This has nothing to do with conspiracy theories. Even less with changing the |
| 81 | world. All I wanted was to get my life back in order and not waste the energy | 80 | world. All I wanted was to get my life back in order and not waste the energy |
| 82 | that could be spent in other, better places. | 81 | that could be spent in other, better places. |
| 83 | 82 | ||
| 84 | I started reading more. I can focus now fully on things I work on. Furthermore, | 83 | I started reading more. I can focus now fully on things I work on. Furthermore, |
| 85 | I have the mental acuity that I never had before. My mind feels sharp. I don't | 84 | I have the mental acuity that I never had before. My mind feels sharp. I don't |
| 86 | get angry so much. I can cherish the finer things in life now without the need | 85 | get angry so much. I can cherish the finer things in life now without the need |
| 87 | to interpret them intellectually. Not only that, but I have a feeling of | 86 | to interpret them intellectually. Not only that, but I have a feeling of |
| 88 | belonging again. Sense of purpose has returned with a vengeance. And I can | 87 | belonging again. Sense of purpose has returned with a vengeance. And I can now |
| 89 | now help people without depleting myself. | 88 | help people without depleting myself. |
| 90 | 89 | ||
| 91 | The last step so far was to finish closing all the remaining online accounts | 90 | The last step so far was to finish closing all the remaining online accounts |
| 92 | that I still had. And when I was thinking what value they bring me, I wasn't | 91 | that I still had. And when I was thinking what value they bring me, I wasn't |
| 93 | surprised that the answer was none. I wasn't logging in them and using them. | 92 | surprised that the answer was none. I wasn't logging in them and using them. I |
| 94 | I stopped being afraid of FOMO. If somebody wants to get in contact me, they | 93 | stopped being afraid of FOMO. If somebody wants to get in contact me, they will |
| 95 | will find a way. I am one search away. | 94 | find a way. I am one search away. |
| 96 | |||
| 97 | We are not beholden to anybody. Our lives are our own. So dare yourself to | ||
| 98 | delete Facebook, LinkedIn. To unsubscribe. Dare yourself to take your time | ||
| 99 | and attention back. Use that time and energy to go for a walk without thinking | ||
| 100 | about work. Read a book instead of reading comment on social media that you | ||
| 101 | will forget in an hour. Enrich your life instead of wasting it. It only | ||
| 102 | requires a small step. And you will feel the benefits immediately. Lose the | ||
| 103 | weight of the world that is crushing you without your consent. | ||
| 104 | 95 | ||
| 96 | We are not beholden to anybody. Our lives are our own. So dare yourself to | ||
| 97 | delete Facebook, LinkedIn. To unsubscribe. Dare yourself to take your time and | ||
| 98 | attention back. Use that time and energy to go for a walk without thinking about | ||
| 99 | work. Read a book instead of reading comment on social media that you will | ||
| 100 | forget in an hour. Enrich your life instead of wasting it. It only requires a | ||
| 101 | small step. And you will feel the benefits immediately. Lose the weight of the | ||
| 102 | world that is crushing you without your consent. | ||
diff --git a/content/posts/2021-12-03-debian-based-riced-up-distribution-for-developers.md b/content/posts/2021-12-03-debian-based-riced-up-distribution-for-developers.md index b8d93a6..0755282 100644 --- a/content/posts/2021-12-03-debian-based-riced-up-distribution-for-developers.md +++ b/content/posts/2021-12-03-debian-based-riced-up-distribution-for-developers.md | |||
| @@ -7,32 +7,33 @@ draft: false | |||
| 7 | 7 | ||
| 8 | ## Introduction | 8 | ## Introduction |
| 9 | 9 | ||
| 10 | I have been using [Ubuntu](https://ubuntu.com/) for quite a longtime now. I | 10 | I have been using [Ubuntu](https://ubuntu.com/) for quite a longtime now. I have |
| 11 | have used [Debian](https://www.debian.org/) in the past and [Manjaro](https://manjaro.org/). | 11 | used [Debian](https://www.debian.org/) in the past and |
| 12 | Also had [Arch](https://archlinux.org/) for some time and even ran | 12 | [Manjaro](https://manjaro.org/). Also had [Arch](https://archlinux.org/) for |
| 13 | [Gentoo](https://www.gentoo.org/) way back. | 13 | some time and even ran [Gentoo](https://www.gentoo.org/) way back. |
| 14 | 14 | ||
| 15 | What I learned from all this is that I prefer running a bit older versions and | 15 | What I learned from all this is that I prefer running a bit older versions and |
| 16 | having them be stable than run bleeding edge rolling release. For that reason, | 16 | having them be stable than run bleeding edge rolling release. For that reason, I |
| 17 | I stuck with Ubuntu for a couple of years now. I am also at a point in my life | 17 | stuck with Ubuntu for a couple of years now. I am also at a point in my life |
| 18 | where I just don't care what is cool or hip anymore. I just want a stable | 18 | where I just don't care what is cool or hip anymore. I just want a stable system |
| 19 | system that doesn't get in my way. | 19 | that doesn't get in my way. |
| 20 | 20 | ||
| 21 | During all this, I noticed that these distributions were getting very bloated | 21 | During all this, I noticed that these distributions were getting very bloated |
| 22 | and a lot of software got included that I usually uninstall on fresh | 22 | and a lot of software got included that I usually uninstall on fresh |
| 23 | installation. Maybe this is my OCD speaking, but why do I have to give fresh | 23 | installation. Maybe this is my OCD speaking, but why do I have to give fresh |
| 24 | installation min 1 GB of ram out of the box just to have a blank screen in | 24 | installation min 1 GB of ram out of the box just to have a blank screen in front |
| 25 | front of me? I get it, there are many things included in the distro to make my | 25 | of me? I get it, there are many things included in the distro to make my life |
| 26 | life easier. I understand. But at this point I have a feeling that modern Linux | 26 | easier. I understand. But at this point I have a feeling that modern Linux |
| 27 | distributions are becoming similar to [Node.js project with node_modules](https://devhumor.com/content/uploads/images/August2017/node-modules.jpg). | 27 | distributions are becoming similar to [Node.js project with |
| 28 | Just a crazy number of packages serving very little or no purpose, just | 28 | node_modules](https://devhumor.com/content/uploads/images/August2017/node-modules.jpg). |
| 29 | Just a crazy number of packages serving very little or no purpose, just | ||
| 29 | supporting other software. | 30 | supporting other software. |
| 30 | 31 | ||
| 31 | I felt I needed a fresh start. To start over with something minimal and clean. | 32 | I felt I needed a fresh start. To start over with something minimal and clean. |
| 32 | Something that would put a little more joy into using a computer again. | 33 | Something that would put a little more joy into using a computer again. |
| 33 | 34 | ||
| 34 | For the first version, I wanted to target the following machines I have at | 35 | For the first version, I wanted to target the following machines I have at home |
| 35 | home that I want this thing to work on. | 36 | that I want this thing to work on. |
| 36 | 37 | ||
| 37 | ```yaml | 38 | ```yaml |
| 38 | # My main stationary work machine | 39 | # My main stationary work machine |
| @@ -52,11 +53,11 @@ Memory: 15891MiB | |||
| 52 | 53 | ||
| 53 | ## How should I approach this? | 54 | ## How should I approach this? |
| 54 | 55 | ||
| 55 | I knew I wanted to use [minimal Debian netinst ](https://www.debian.org/CD/netinst/) | 56 | I knew I wanted to use [minimal Debian netinst |
| 56 | for the base to give myself a head start. No reason to go through changing the | 57 | ](https://www.debian.org/CD/netinst/) for the base to give myself a head |
| 57 | installer and also testing all that behemoth of a thing. So, some sort of | 58 | start. No reason to go through changing the installer and also testing all that |
| 58 | ricing was the only logical option to get this thing of the grounds somewhat | 59 | behemoth of a thing. So, some sort of ricing was the only logical option to get |
| 59 | quickly. | 60 | this thing of the grounds somewhat quickly. |
| 60 | 61 | ||
| 61 | > **What is ricing anyway?** | 62 | > **What is ricing anyway?** |
| 62 | > The term “RICE” stands for Race Inspired Cosmetic Enhancement. A group of | 63 | > The term “RICE” stands for Race Inspired Cosmetic Enhancement. A group of |
| @@ -66,9 +67,9 @@ quickly. | |||
| 66 | > than others... For more information, read this article | 67 | > than others... For more information, read this article |
| 67 | > [What in the world is ricing!?](https://pesos.github.io/2020/07/14/what-is-ricing.html). | 68 | > [What in the world is ricing!?](https://pesos.github.io/2020/07/14/what-is-ricing.html). |
| 68 | 69 | ||
| 69 | I didn't want this to just be a set of config files for theming purpose. I | 70 | I didn't want this to just be a set of config files for theming purpose. I |
| 70 | wanted this to include a set of pre-installed tools and services that are being | 71 | wanted this to include a set of pre-installed tools and services that are being |
| 71 | used all the time by a modern developer. Theming is just a tiny part of it. | 72 | used all the time by a modern developer. Theming is just a tiny part of it. |
| 72 | Fonts being applied across the distro and things like that. | 73 | Fonts being applied across the distro and things like that. |
| 73 | 74 | ||
| 74 | First, I choose terminal installer and left it to load additional components. | 75 | First, I choose terminal installer and left it to load additional components. |
| @@ -87,10 +88,9 @@ downloaded from the internet during installation. | |||
| 87 | 88 | ||
| 88 |  | 89 |  |
| 89 | 90 | ||
| 90 | 91 | I opted out of the popularity contest, and **now comes the important part**. | |
| 91 | I opted out of the popularity contest, and **now comes the important part**. | 92 | Uncheck all the boxes in Software selection and only leave 'standard system |
| 92 | Uncheck all the boxes in Software selection and only leave 'standard system | 93 | utilities'. I also left an SSH server, so I was able to log in to the machine |
| 93 | utilities'. I also left an SSH server, so I was able to log in to the machine | ||
| 94 | from my main PC. | 94 | from my main PC. |
| 95 | 95 | ||
| 96 |  | 96 |  |
| @@ -100,50 +100,49 @@ system. | |||
| 100 | 100 | ||
| 101 |  | 101 |  |
| 102 | 102 | ||
| 103 | That concluded the installation of base Debian and after restarting the | 103 | That concluded the installation of base Debian and after restarting the computer |
| 104 | computer I was prompted with the login screen. | 104 | I was prompted with the login screen. |
| 105 | 105 | ||
| 106 |  | 106 |  |
| 107 | 107 | ||
| 108 | Now that I had the base installation, it was time to choose what software do I | 108 | Now that I had the base installation, it was time to choose what software do I |
| 109 | want to include in this so-called distribution. I wanted out of the box | 109 | want to include in this so-called distribution. I wanted out of the box |
| 110 | developer experience, so I had plenty to choose. | 110 | developer experience, so I had plenty to choose. |
| 111 | 111 | ||
| 112 | Let's not waste time and go through the list. | 112 | Let's not waste time and go through the list. |
| 113 | 113 | ||
| 114 | ## Desktop environments | 114 | ## Desktop environments |
| 115 | 115 | ||
| 116 | I have been using [Gnome](https://www.gnome.org/) for my whole Linux life. | 116 | I have been using [Gnome](https://www.gnome.org/) for my whole Linux life. From |
| 117 | From version 2 forward. It's been quite a ride. I hated version 3 when it | 117 | version 2 forward. It's been quite a ride. I hated version 3 when it came out |
| 118 | came out and replaced version 2. But I got used to it. And now with version | 118 | and replaced version 2. But I got used to it. And now with version 40+ they also |
| 119 | 40+ they also made couple of changes which I found both frustrating and | 119 | made couple of changes which I found both frustrating and presently surprised. |
| 120 | presently surprised. | ||
| 121 | 120 | ||
| 122 | The amount of vertical space you loose because of the beefy title bars on | 121 | The amount of vertical space you loose because of the beefy title bars on |
| 123 | windows is ridiculous. And then in case of [Tilix](https://gnunn1.github.io/tilix-web/) | 122 | windows is ridiculous. And then in case of |
| 124 | you also have tabs, and you are 100px deep. Vertical space is one of the most | 123 | [Tilix](https://gnunn1.github.io/tilix-web/) you also have tabs, and you are |
| 125 | important things for a developer. The more real estate you have, the more | 124 | 100px deep. Vertical space is one of the most important things for a |
| 126 | code you can have in a viewport. | 125 | developer. The more real estate you have, the more code you can have in a |
| 126 | viewport. | ||
| 127 | 127 | ||
| 128 | But on the other hand, I still love how Gnome feels and looks. I gotta give | 128 | But on the other hand, I still love how Gnome feels and looks. I gotta give them |
| 129 | them that. They really are trying to make Gnome feel unified and modern. | 129 | that. They really are trying to make Gnome feel unified and modern. |
| 130 | 130 | ||
| 131 | Regardless of all the nice things Gnome has, I was looking at the tiling | 131 | Regardless of all the nice things Gnome has, I was looking at the tiling window |
| 132 | window managers for some time, but never had the nerve to actually go with | 132 | managers for some time, but never had the nerve to actually go with it. But now |
| 133 | it. But now was the ideal time to give it a go. No guts, no glory kind of | 133 | was the ideal time to give it a go. No guts, no glory kind of a thing. |
| 134 | a thing. | ||
| 135 | 134 | ||
| 136 | One of the requirements for me was easy custom layouts because I use a really | 135 | One of the requirements for me was easy custom layouts because I use a really |
| 137 | strange monitor with aspect ratio of 32:9. So relying on included layouts | 136 | strange monitor with aspect ratio of 32:9. So relying on included layouts most |
| 138 | most of them have is a non-starter. | 137 | of them have is a non-starter. |
| 139 | 138 | ||
| 140 | What I was doing in Gnome was having windows in a layout like the diagram | 139 | What I was doing in Gnome was having windows in a layout like the diagram |
| 141 | below. This is my common practice. And if you look at it you can clearly see | 140 | below. This is my common practice. And if you look at it you can clearly see I |
| 142 | I was replicating tiling window manager setup in Gnome. | 141 | was replicating tiling window manager setup in Gnome. |
| 143 | 142 | ||
| 144 |  | 143 |  |
| 145 | 144 | ||
| 146 | That made me look into a bunch of tiling window managers and then tested them | 145 | That made me look into a bunch of tiling window managers and then tested them |
| 147 | out. Candidates I was looking at were: | 146 | out. Candidates I was looking at were: |
| 148 | 147 | ||
| 149 | - [i3](https://i3wm.org/) | 148 | - [i3](https://i3wm.org/) |
| @@ -154,18 +153,20 @@ out. Candidates I was looking at were: | |||
| 154 | - [Qtile](http://www.qtile.org/) | 153 | - [Qtile](http://www.qtile.org/) |
| 155 | - [dwm](https://dwm.suckless.org/) | 154 | - [dwm](https://dwm.suckless.org/) |
| 156 | 155 | ||
| 157 | You can also check article [13 Best Tiling Window Managers for Linux](https://www.tecmint.com/best-tiling-window-managers-for-linux/) | 156 | You can also check article [13 Best Tiling Window Managers for |
| 158 | I was referencing while testing them out. | 157 | Linux](https://www.tecmint.com/best-tiling-window-managers-for-linux/) I was |
| 158 | referencing while testing them out. | ||
| 159 | 159 | ||
| 160 | While all of them provided what I needed, I liked i3 the most. What particular | 160 | While all of them provided what I needed, I liked i3 the most. What particular |
| 161 | caught my eye was the ease to use and tree based layouts which allows flexible | 161 | caught my eye was the ease to use and tree based layouts which allows flexible |
| 162 | layouts. I know others can be set up also to have custom layouts other than | 162 | layouts. I know others can be set up also to have custom layouts other than |
| 163 | spiral, dwindle etc. I think i3 is a good entry-level window manager for | 163 | spiral, dwindle etc. I think i3 is a good entry-level window manager for |
| 164 | somebody like me. | 164 | somebody like me. |
| 165 | 165 | ||
| 166 | ## Batteries included | 166 | ## Batteries included |
| 167 | 167 | ||
| 168 | The source for the whole thing is located on Github https://github.com/mitjafelicijan/dfd-rice. | 168 | The source for the whole thing is located on Github |
| 169 | https://github.com/mitjafelicijan/dfd-rice. | ||
| 169 | 170 | ||
| 170 | Currenly included: | 171 | Currenly included: |
| 171 | 172 | ||
| @@ -193,7 +194,7 @@ Currenly included: | |||
| 193 | - `docker` (with docker-compose) | 194 | - `docker` (with docker-compose) |
| 194 | - `ansible` | 195 | - `ansible` |
| 195 | 196 | ||
| 196 | Install script also allows you to install only specific packages (example for: | 197 | Install script also allows you to install only specific packages (example for: |
| 197 | essentials ohmybash docker rust). | 198 | essentials ohmybash docker rust). |
| 198 | 199 | ||
| 199 | ```sh | 200 | ```sh |
| @@ -202,10 +203,10 @@ su - root \ | |||
| 202 | essentials ohmybash docker rust | 203 | essentials ohmybash docker rust |
| 203 | ``` | 204 | ``` |
| 204 | 205 | ||
| 205 | Currently, most of these recipes use what Debian and this is totally fine with | 206 | Currently, most of these recipes use what Debian and this is totally fine with |
| 206 | me since I never use bleeding edge features of a package. But if something | 207 | me since I never use bleeding edge features of a package. But if something major |
| 207 | major would come to light, I will replace it with a possible compilation | 208 | would come to light, I will replace it with a possible compilation script or |
| 208 | script or something similar. | 209 | something similar. |
| 209 | 210 | ||
| 210 | This is some of the output from the installation script. | 211 | This is some of the output from the installation script. |
| 211 | 212 | ||
| @@ -232,11 +233,11 @@ systemctl status docker --no-pager | |||
| 232 | 233 | ||
| 233 | ### Making bash pretty | 234 | ### Making bash pretty |
| 234 | 235 | ||
| 235 | I really like [Oh My Zsh](https://ohmyz.sh/), but I don't like zsh shell. | 236 | I really like [Oh My Zsh](https://ohmyz.sh/), but I don't like zsh shell. When |
| 236 | When I used it, I constantly needed to be aware of it and running bash scripts | 237 | I used it, I constantly needed to be aware of it and running bash scripts was a |
| 237 | was a pain. So, I was really delighted when I found out that a version for | 238 | pain. So, I was really delighted when I found out that a version for bash |
| 238 | bash existed called [Oh My Bash](https://ohmybash.nntoan.com/). Let's take a | 239 | existed called [Oh My Bash](https://ohmybash.nntoan.com/). Let's take a look at |
| 239 | look at the recipe for installing it. | 240 | the recipe for installing it. |
| 240 | 241 | ||
| 241 | ```sh | 242 | ```sh |
| 242 | # ohmybash | 243 | # ohmybash |
| @@ -246,29 +247,29 @@ T1=${!} | |||
| 246 | wait ${T1} | 247 | wait ${T1} |
| 247 | ``` | 248 | ``` |
| 248 | 249 | ||
| 249 | Because OhMyBash does `exec bash` at the end, this traps our script inside | 250 | Because OhMyBash does `exec bash` at the end, this traps our script inside |
| 250 | another shell and our script cannot continue. For that reason, I executed | 251 | another shell and our script cannot continue. For that reason, I executed this |
| 251 | this in background. But that presents a new problem. Because this is executed | 252 | in background. But that presents a new problem. Because this is executed in |
| 252 | in background, we lose track of progress naturally. And that strange trick | 253 | background, we lose track of progress naturally. And that strange trick with |
| 253 | with `T1=${!}` and `wait ${T1}` waits for the background process to finish | 254 | `T1=${!}` and `wait ${T1}` waits for the background process to finish before |
| 254 | before continuing to another task in bash script. | 255 | continuing to another task in bash script. |
| 255 | 256 | ||
| 256 | Check [Multi-Threaded Processing in Bash Scripts](https://www.cloudsavvyit.com/12277/how-to-use-multi-threaded-processing-in-bash-scripts/) | 257 | Check [Multi-Threaded Processing in Bash Scripts](https://www.cloudsavvyit.com/12277/how-to-use-multi-threaded-processing-in-bash-scripts/) |
| 257 | for more details. | 258 | for more details. |
| 258 | 259 | ||
| 259 | ## Conclusion | 260 | ## Conclusion |
| 260 | 261 | ||
| 261 | Take a look at https://github.com/mitjafelicijan/dfd-rice/blob/develop/tools/install.sh | 262 | Take a look at |
| 262 | script to get familiar with it. This is just a first iteration and I will | 263 | https://github.com/mitjafelicijan/dfd-rice/blob/develop/tools/install.sh script |
| 263 | continue to update it because I need this in my life. | 264 | to get familiar with it. This is just a first iteration and I will continue to |
| 265 | update it because I need this in my life. | ||
| 264 | 266 | ||
| 265 | The current version boots in 4s to the login prompt, and after you log in, | 267 | The current version boots in 4s to the login prompt, and after you log in, the |
| 266 | the desktop environment loads in 2s. So, its fast, very fast. And on clean | 268 | desktop environment loads in 2s. So, its fast, very fast. And on clean boot, I |
| 267 | boot, I measured ~230 MB of RAM usage. | 269 | measured ~230 MB of RAM usage. |
| 268 | 270 | ||
| 269 | And this is how it looks with two terminals side by side. I really like the | 271 | And this is how it looks with two terminals side by side. I really like the |
| 270 | simplicity and clean interface. I will polish the colors and stuff like that, | 272 | simplicity and clean interface. I will polish the colors and stuff like that, |
| 271 | but I really do like the results. | 273 | but I really do like the results. |
| 272 | 274 | ||
| 273 |  | 275 |  |
| 274 | |||
diff --git a/content/posts/2021-12-25-running-golang-application-as-pid1.md b/content/posts/2021-12-25-running-golang-application-as-pid1.md index e3b7fa2..60d0400 100644 --- a/content/posts/2021-12-25-running-golang-application-as-pid1.md +++ b/content/posts/2021-12-25-running-golang-application-as-pid1.md | |||
| @@ -7,9 +7,10 @@ draft: false | |||
| 7 | 7 | ||
| 8 | ## Unikernels, kernels, and alike | 8 | ## Unikernels, kernels, and alike |
| 9 | 9 | ||
| 10 | I have been reading a lot about [unikernernels](https://en.wikipedia.org/wiki/Unikernel) | 10 | I have been reading a lot about |
| 11 | lately and found them very intriguing. When you push away all the marketing | 11 | [unikernernels](https://en.wikipedia.org/wiki/Unikernel) lately and found them |
| 12 | speak and look at the idea, it makes a lot of sense. | 12 | very intriguing. When you push away all the marketing speak and look at the |
| 13 | idea, it makes a lot of sense. | ||
| 13 | 14 | ||
| 14 | > A unikernel is a specialized, single address space machine image constructed | 15 | > A unikernel is a specialized, single address space machine image constructed |
| 15 | > by using library operating systems. ([Wikipedia](https://en.wikipedia.org/wiki/Unikernel)) | 16 | > by using library operating systems. ([Wikipedia](https://en.wikipedia.org/wiki/Unikernel)) |
diff --git a/content/posts/2021-12-30-wap-mobile-web-before-the-web.md b/content/posts/2021-12-30-wap-mobile-web-before-the-web.md index 1ee82b5..6c598fe 100644 --- a/content/posts/2021-12-30-wap-mobile-web-before-the-web.md +++ b/content/posts/2021-12-30-wap-mobile-web-before-the-web.md | |||
| @@ -7,14 +7,15 @@ draft: false | |||
| 7 | 7 | ||
| 8 | ## A little stroll down the history lane | 8 | ## A little stroll down the history lane |
| 9 | 9 | ||
| 10 | About two weeks ago, I watched this outstanding documentary on YouTube | 10 | About two weeks ago, I watched this outstanding documentary on YouTube |
| 11 | [Springboard: the secret history of the first real smartphone](https://www.youtube.com/watch?v=b9_Vh9h3Ohw) | 11 | [Springboard: the secret history of the first real |
| 12 | about the history of smartphones and phones in general. It brought back so many | 12 | smartphone](https://www.youtube.com/watch?v=b9_Vh9h3Ohw) about the history of |
| 13 | memories. I never had an actual smartphone before the Android. The closest to | 13 | smartphones and phones in general. It brought back so many memories. I never had |
| 14 | smartphone was [Sony Ericsson P1](https://www.gsmarena.com/sony_ericsson_p1-1982.php). | 14 | an actual smartphone before the Android. The closest to smartphone was [Sony |
| 15 | A fantastic phone and I broke it in Prague after a party and that was one of | 15 | Ericsson P1](https://www.gsmarena.com/sony_ericsson_p1-1982.php). A fantastic |
| 16 | those rare occasions where I was actually mad at myself. But nevertheless, | 16 | phone and I broke it in Prague after a party and that was one of those rare |
| 17 | after that phone, the next one was an Android one. | 17 | occasions where I was actually mad at myself. But nevertheless, after that |
| 18 | phone, the next one was an Android one. | ||
| 18 | 19 | ||
| 19 | Before that, I only owned normal phones from Nokia and Siemens etc. Nothing | 20 | Before that, I only owned normal phones from Nokia and Siemens etc. Nothing |
| 20 | special, actually. These are the phones we are talking about. Before 2007. | 21 | special, actually. These are the phones we are talking about. Before 2007. |
| @@ -34,42 +35,42 @@ Let's take a look at these beauties. | |||
| 34 | 35 | ||
| 35 | ## WAP - Wireless Application Protocol | 36 | ## WAP - Wireless Application Protocol |
| 36 | 37 | ||
| 37 | Not that one! We are talking about Wireless Application Protocol and not | 38 | Not that one! We are talking about Wireless Application Protocol and not Cardi |
| 38 | Cardi B's song 😃 | 39 | B's song 😃 |
| 39 | 40 | ||
| 40 | WAP stands for Wireless Application Protocol. It is a protocol designed for | 41 | WAP stands for Wireless Application Protocol. It is a protocol designed for |
| 41 | micro-browsers, and it enables the access of internet in the mobile devices. | 42 | micro-browsers, and it enables the access of internet in the mobile devices. It |
| 42 | It uses the mark-up language WML (Wireless Markup Language and not HTML), WML | 43 | uses the mark-up language WML (Wireless Markup Language and not HTML), WML is |
| 43 | is defined as XML 1.0 application. Furthermore, it enables creating web | 44 | defined as XML 1.0 application. Furthermore, it enables creating web |
| 44 | applications for mobile devices. In 1998, WAP Forum was founded by Ericson, | 45 | applications for mobile devices. In 1998, WAP Forum was founded by Ericson, |
| 45 | Motorola, Nokia and Unwired Planet whose aim was to standardize the various | 46 | Motorola, Nokia and Unwired Planet whose aim was to standardize the various |
| 46 | wireless technologies via protocols. | 47 | wireless technologies via protocols. |
| 47 | [(source)](https://www.geeksforgeeks.org/wireless-application-protocol/) | 48 | [(source)](https://www.geeksforgeeks.org/wireless-application-protocol/) |
| 48 | 49 | ||
| 49 | WAP protocol was resulted by the joint efforts of the various members of WAP | 50 | WAP protocol was resulted by the joint efforts of the various members of WAP |
| 50 | Forum. In 2002, WAP forum was merged with various other forums of the industry, | 51 | Forum. In 2002, WAP forum was merged with various other forums of the industry, |
| 51 | resulting in the formation of Open Mobile Alliance (OMA). | 52 | resulting in the formation of Open Mobile Alliance (OMA). |
| 52 | [(source)](https://www.geeksforgeeks.org/wireless-application-protocol/) | 53 | [(source)](https://www.geeksforgeeks.org/wireless-application-protocol/) |
| 53 | 54 | ||
| 54 | These were some wild times. Devices had tiny screens and data transmission rates | 55 | These were some wild times. Devices had tiny screens and data transmission rates |
| 55 | were abominable. But they were capable of rendering WML (Wireless Markup | 56 | were abominable. But they were capable of rendering WML (Wireless Markup |
| 56 | Language). This was very similar to HTML, actually. It is a markup language, | 57 | Language). This was very similar to HTML, actually. It is a markup language, |
| 57 | after all. | 58 | after all. |
| 58 | 59 | ||
| 59 | These pages could be served by [Apache](https://apache.org/) and could be | 60 | These pages could be served by [Apache](https://apache.org/) and could be |
| 60 | generated by CGI scripts on the backend. The only difference was the limited | 61 | generated by CGI scripts on the backend. The only difference was the limited |
| 61 | markup language. | 62 | markup language. |
| 62 | 63 | ||
| 63 | ## WML - Wireless Markup Language | 64 | ## WML - Wireless Markup Language |
| 64 | 65 | ||
| 65 | Just like web browsers use HTML for content structure, older mobile device | 66 | Just like web browsers use HTML for content structure, older mobile device |
| 66 | browsers use WML - if you need to support really old mobile phones using WML | 67 | browsers use WML - if you need to support really old mobile phones using WML |
| 67 | browsers, you will need to know about it. WML is XML-based (an XML vocabulary | 68 | browsers, you will need to know about it. WML is XML-based (an XML vocabulary |
| 68 | just like XHTML and MathML, but not HTML) and does not use the same metaphor | 69 | just like XHTML and MathML, but not HTML) and does not use the same metaphor as |
| 69 | as HTML. HTML is a single document with some metadata packed away in the head, | 70 | HTML. HTML is a single document with some metadata packed away in the head, and |
| 70 | and a body encapsulating the visible page. With WML, the metaphor does not | 71 | a body encapsulating the visible page. With WML, the metaphor does not envisage |
| 71 | envisage a page, but rather a deck of cards. A WML file might have several | 72 | a page, but rather a deck of cards. A WML file might have several pages or cards |
| 72 | pages or cards contained within it. | 73 | contained within it. |
| 73 | [(source)](https://www.w3.org/wiki/Introduction_to_mobile_web) | 74 | [(source)](https://www.w3.org/wiki/Introduction_to_mobile_web) |
| 74 | 75 | ||
| 75 | ```html | 76 | ```html |
| @@ -82,7 +83,8 @@ pages or cards contained within it. | |||
| 82 | </wml> | 83 | </wml> |
| 83 | ``` | 84 | ``` |
| 84 | 85 | ||
| 85 | There is an amazing tutorial on [Tutorialpoint about WML](https://www.tutorialspoint.com/wml/index.htm). | 86 | There is an amazing tutorial on [Tutorialpoint about |
| 87 | WML](https://www.tutorialspoint.com/wml/index.htm). | ||
| 86 | 88 | ||
| 87 | ## Converting Digg to WML | 89 | ## Converting Digg to WML |
| 88 | 90 | ||
| @@ -166,24 +168,24 @@ with open('www/index.wml', 'w+') as fp: | |||
| 166 | fp.write(html) | 168 | fp.write(html) |
| 167 | ``` | 169 | ``` |
| 168 | 170 | ||
| 169 | This script will create a folder `www` and in the folder `www/images` for | 171 | This script will create a folder `www` and in the folder `www/images` for |
| 170 | storing resized images. | 172 | storing resized images. |
| 171 | 173 | ||
| 172 | > Be sure you don't use SSL and use just normal HTTP for serving the content. | 174 | > Be sure you don't use SSL and use just normal HTTP for serving the content. |
| 173 | > These old phones will have problems with TLS 1.3 etc. | 175 | > These old phones will have problems with TLS 1.3 etc. |
| 174 | 176 | ||
| 175 | If you look at the python file, I convert all the images into tiny B&W images. | 177 | If you look at the python file, I convert all the images into tiny B&W images. |
| 176 | They should be WBMP (Wireless BitMaP) but I choose JPEGs for this, and it | 178 | They should be WBMP (Wireless BitMaP) but I choose JPEGs for this, and it seems |
| 177 | seems to work properly. | 179 | to work properly. |
| 178 | 180 | ||
| 179 | Because I currently don't have a phone old enough to test it on, I used an | 181 | Because I currently don't have a phone old enough to test it on, I used an |
| 180 | emulator. And it was really hard to find one. I found [WAP Proof](http://wap-proof.sharewarejunction.com/) | 182 | emulator. And it was really hard to find one. I found [WAP |
| 181 | on shareware junction, and it did the job well enough. I will try to find and | 183 | Proof](http://wap-proof.sharewarejunction.com/) on shareware junction, and it |
| 182 | actual device to test it on. | 184 | did the job well enough. I will try to find and actual device to test it on. |
| 183 | 185 | ||
| 184 | <video src="/assets/wap/emulator.mp4" controls></video> | 186 | <video src="/assets/wap/emulator.mp4" controls></video> |
| 185 | 187 | ||
| 186 | If you are using Nginx to serve the contents, add a directive to the hosts file | 188 | If you are using Nginx to serve the contents, add a directive to the hosts file |
| 187 | that will automatically server `index.wml` file. | 189 | that will automatically server `index.wml` file. |
| 188 | 190 | ||
| 189 | ```nginx | 191 | ```nginx |
| @@ -195,6 +197,5 @@ server { | |||
| 195 | ## Conclusion | 197 | ## Conclusion |
| 196 | 198 | ||
| 197 | Well, this was pointless, but very fun! I hope you enjoyed it as much as I did. | 199 | Well, this was pointless, but very fun! I hope you enjoyed it as much as I did. |
| 198 | I will try to find an old phone to test it on. If you have any questions, | 200 | I will try to find an old phone to test it on. If you have any questions, feel |
| 199 | feel free to ask in the comments. | 201 | free to ask in the comments. |
| 200 | |||
diff --git a/content/posts/2022-06-30-trying-out-helix-editor.md b/content/posts/2022-06-30-trying-out-helix-editor.md index c1da4a5..23c1cf3 100644 --- a/content/posts/2022-06-30-trying-out-helix-editor.md +++ b/content/posts/2022-06-30-trying-out-helix-editor.md | |||
| @@ -5,27 +5,27 @@ date: 2022-06-30T12:00:00+02:00 | |||
| 5 | draft: false | 5 | draft: false |
| 6 | --- | 6 | --- |
| 7 | 7 | ||
| 8 | I have been searching for a lightweight code editor for quite some time. One of | 8 | I have been searching for a lightweight code editor for quite some time. One of |
| 9 | the main reasons was that I wanted something that doesn't burn through CPU and | 9 | the main reasons was that I wanted something that doesn't burn through CPU and |
| 10 | RAM usage is not through the roof. I have been mostly using Visual Studio Code. | 10 | RAM usage is not through the roof. I have been mostly using Visual Studio Code. |
| 11 | It's been an outstanding editor. I have no quarrel with it at all. It's just | 11 | It's been an outstanding editor. I have no quarrel with it at all. It's just |
| 12 | time to spice life up with something new. | 12 | time to spice life up with something new. |
| 13 | 13 | ||
| 14 | I have been on this search for a couple of years. I have tried Vim, Neovim, | 14 | I have been on this search for a couple of years. I have tried Vim, Neovim, |
| 15 | Emacs, Doom Emacs, Micro and couple more. Among most of them, I liked Micro | 15 | Emacs, Doom Emacs, Micro and couple more. Among most of them, I liked Micro and |
| 16 | and Doom Emacs the most. Micro editor was a little too basic for me. And Doom | 16 | Doom Emacs the most. Micro editor was a little too basic for me. And Doom Emacs |
| 17 | Emacs was a bit too hardcore. This does not reflect on any of the editors. It's | 17 | was a bit too hardcore. This does not reflect on any of the editors. It's just |
| 18 | just my personal preference. | 18 | my personal preference. |
| 19 | 19 | ||
| 20 | > I tried Helix Editor about a year ago. But I didn't pay attention to it. | 20 | > I tried Helix Editor about a year ago. But I didn't pay attention to it. |
| 21 | > Tried it and saw it's similar to Vi and just said no. I was premature to | 21 | > Tried it and saw it's similar to Vi and just said no. I was premature to |
| 22 | > dismiss it. | 22 | > dismiss it. |
| 23 | 23 | ||
| 24 | One of the things I actually miss is line wrapping for certain files. When | 24 | One of the things I actually miss is line wrapping for certain files. When |
| 25 | writing Markdown, line wrapping would be very helpful. Editing such a document | 25 | writing Markdown, line wrapping would be very helpful. Editing such a document |
| 26 | is frustrating to say the least. Some of the Markdown to HTML converters don't | 26 | is frustrating to say the least. Some of the Markdown to HTML converters don't |
| 27 | take kindly of new lines between sentences. Not paragraphs, sentences. And I | 27 | take kindly of new lines between sentences. Not paragraphs, sentences. And I use |
| 28 | use Markdown to write this blog you are reading. | 28 | Markdown to write this blog you are reading. |
| 29 | 29 | ||
| 30 | But other than this, I have been extremely satisfied by it. It's been a pleasant | 30 | But other than this, I have been extremely satisfied by it. It's been a pleasant |
| 31 | surprise. There have been zero issues with the editor. | 31 | surprise. There have been zero issues with the editor. |
| @@ -39,15 +39,14 @@ npm install -g typescript typescript-language-server | |||
| 39 | 39 | ||
| 40 | I am still getting used to the keyboard shortcuts and getting better. What Helix | 40 | I am still getting used to the keyboard shortcuts and getting better. What Helix |
| 41 | does really well is packing in sane defaults and even though because currently | 41 | does really well is packing in sane defaults and even though because currently |
| 42 | there is no plugin support I haven't found any need for them. It has all that | 42 | there is no plugin support I haven't found any need for them. It has all that |
| 43 | you would need. It goes to extreme measures to show a user what is going on | 43 | you would need. It goes to extreme measures to show a user what is going on with |
| 44 | with popups that show you what the keyboard shortcuts are. | 44 | popups that show you what the keyboard shortcuts are. |
| 45 | 45 | ||
| 46 | And it comes us packed with many | 46 | And it comes us packed with many |
| 47 | [really good themes](https://github.com/helix-editor/helix/wiki/Themes). | 47 | [really good themes](https://github.com/helix-editor/helix/wiki/Themes). |
| 48 | 48 | ||
| 49 |  | 49 |  |
| 50 | 50 | ||
| 51 | It's still young but has this mature feeling to it. It has sane defaults and | 51 | It's still young but has this mature feeling to it. It has sane defaults and |
| 52 | mimics Vim (works a bit differently, but the overall idea is similar). | 52 | mimics Vim (works a bit differently, but the overall idea is similar). |
| 53 | |||
diff --git a/content/posts/2022-07-05-what-would-dna-sound-if-synthesized.md b/content/posts/2022-07-05-what-would-dna-sound-if-synthesized.md index 15bbf2b..e26088b 100644 --- a/content/posts/2022-07-05-what-would-dna-sound-if-synthesized.md +++ b/content/posts/2022-07-05-what-would-dna-sound-if-synthesized.md | |||
| @@ -7,37 +7,38 @@ draft: false | |||
| 7 | 7 | ||
| 8 | ## Introduction | 8 | ## Introduction |
| 9 | 9 | ||
| 10 | Lately, I have been thinking a lot about the nature of life, what are the | 10 | Lately, I have been thinking a lot about the nature of life, what are the |
| 11 | foundation blocks of life and things like that. It's remarkable how complex | 11 | foundation blocks of life and things like that. It's remarkable how complex and |
| 12 | and on the other hand simple the creation is when you look at it. The miracle | 12 | on the other hand simple the creation is when you look at it. The miracle of |
| 13 | of life keeps us grounded when our imagination goes wild. If the DNA are the | 13 | life keeps us grounded when our imagination goes wild. If the DNA are the blocks |
| 14 | blocks of life, you could consider them to be an API nature provided us to | 14 | of life, you could consider them to be an API nature provided us to better |
| 15 | better understand all of this chaos masquerading as order. | 15 | understand all of this chaos masquerading as order. |
| 16 | 16 | ||
| 17 | I have been reading a lot about superintelligence and our somehow misguided | 17 | I have been reading a lot about superintelligence and our somehow misguided path |
| 18 | path to create general artificial intelligence. What would the building blocks | 18 | to create general artificial intelligence. What would the building blocks or our |
| 19 | or our creation look like? Is the compression really the ultimate storage of | 19 | creation look like? Is the compression really the ultimate storage of |
| 20 | information? Will our creation also ponder this questions when creating new | 20 | information? Will our creation also ponder this questions when creating new |
| 21 | worlds for themselves, or will we just disappear into the vastness of | 21 | worlds for themselves, or will we just disappear into the vastness of |
| 22 | possibilities? It is a little offensive that we are playing God whilst being | 22 | possibilities? It is a little offensive that we are playing God whilst being |
| 23 | completely ignorant of our own reality. Who knows! Like many other | 23 | completely ignorant of our own reality. Who knows! Like many other |
| 24 | breakthroughs, this one will also come at a cost not known to us when it | 24 | breakthroughs, this one will also come at a cost not known to us when it finally |
| 25 | finally happens. | 25 | happens. |
| 26 | 26 | ||
| 27 | To keep things a bit lighter, I decided to convert some popular DNA sequences | 27 | To keep things a bit lighter, I decided to convert some popular DNA sequences |
| 28 | into an audio files for us to listen to. I am not the first one, nor I will be | 28 | into an audio files for us to listen to. I am not the first one, nor I will be |
| 29 | the last one to do this. But it is an interesting exercise in better | 29 | the last one to do this. But it is an interesting exercise in better |
| 30 | understanding the relationship between art and science. Maybe listening to DNA | 30 | understanding the relationship between art and science. Maybe listening to DNA |
| 31 | instead of parsing it will find a way into better understanding, or at least | 31 | instead of parsing it will find a way into better understanding, or at least |
| 32 | enjoying the creation and cryptic nature of life. | 32 | enjoying the creation and cryptic nature of life. |
| 33 | 33 | ||
| 34 | ## DNA encoding and primer example | 34 | ## DNA encoding and primer example |
| 35 | 35 | ||
| 36 | I have been exploring DNA in the past in my post from about 3 years ago in | 36 | I have been exploring DNA in the past in my post from about 3 years ago in |
| 37 | [Encoding binary data into DNA sequence](/encoding-binary-data-into-dna-sequence.html) | 37 | [Encoding binary data into DNA |
| 38 | where I have been converting all sorts of data into DNA sequences. | 38 | sequence](/encoding-binary-data-into-dna-sequence.html) where I have been |
| 39 | converting all sorts of data into DNA sequences. | ||
| 39 | 40 | ||
| 40 | This will be a similar exercise but instead of converting to DNA, I will be | 41 | This will be a similar exercise but instead of converting to DNA, I will be |
| 41 | generating tones from Nucleotides. | 42 | generating tones from Nucleotides. |
| 42 | 43 | ||
| 43 | | Nucleotides | Note | Frequency | | 44 | | Nucleotides | Note | Frequency | |
| @@ -49,12 +50,13 @@ generating tones from Nucleotides. | |||
| 49 | 50 | ||
| 50 | Since we do not have T in equal-tempered scale, I choose D to represent T note. | 51 | Since we do not have T in equal-tempered scale, I choose D to represent T note. |
| 51 | 52 | ||
| 52 | You can check [Frequencies for equal-tempered scale, A4 = 440 Hz](https://pages.mtu.edu/~suits/notefreqs.html). | 53 | You can check [Frequencies for equal-tempered scale, A4 = 440 |
| 53 | For this tuning, we also choose `Speed of Sound = 345 m/s = 1130 ft/s = 770 miles/hr`. | 54 | Hz](https://pages.mtu.edu/~suits/notefreqs.html). For this tuning, we also |
| 55 | choose `Speed of Sound = 345 m/s = 1130 ft/s = 770 miles/hr`. | ||
| 54 | 56 | ||
| 55 | Now that we have this out of the way, we can also brush up on the DNA | 57 | Now that we have this out of the way, we can also brush up on the DNA sequencing |
| 56 | sequencing a bit. This is a famous quote I also used for the encoding tests, | 58 | a bit. This is a famous quote I also used for the encoding tests, and it goes |
| 57 | and it goes like this. | 59 | like this. |
| 58 | 60 | ||
| 59 | > How wonderful that we have met with a paradox. Now we have some hope of | 61 | > How wonderful that we have met with a paradox. Now we have some hope of |
| 60 | > making progress. | 62 | > making progress. |
| @@ -72,16 +74,16 @@ AACCTCACCAAACGGGACAAGATCGCCGGCGGGCTAGTATACAAGAACGCTTGCCAGTAC | |||
| 72 | AACC | 74 | AACC |
| 73 | ``` | 75 | ``` |
| 74 | 76 | ||
| 75 | This is what we gonna work with to get things rolling forward, when creating | 77 | This is what we gonna work with to get things rolling forward, when creating |
| 76 | parser and waveform generator. | 78 | parser and waveform generator. |
| 77 | 79 | ||
| 78 | ## Parsing DNA data | 80 | ## Parsing DNA data |
| 79 | 81 | ||
| 80 | This step is rather simple one. All we need to do is parse input DNA sequence in | 82 | This step is rather simple one. All we need to do is parse input DNA sequence in |
| 81 | [FASTA format](https://en.wikipedia.org/wiki/FASTA_format) well known | 83 | [FASTA format](https://en.wikipedia.org/wiki/FASTA_format) well known in |
| 82 | in [Bioinformatics](https://en.wikipedia.org/wiki/Bioinformatics) to extract | 84 | [Bioinformatics](https://en.wikipedia.org/wiki/Bioinformatics) to extract single |
| 83 | single Nucleotides that will be converted into separate tones based on | 85 | Nucleotides that will be converted into separate tones based on equal-tempered |
| 84 | equal-tempered scale explained above. | 86 | scale explained above. |
| 85 | 87 | ||
| 86 | ```python | 88 | ```python |
| 87 | nucleotide_tone_map = { | 89 | nucleotide_tone_map = { |
| @@ -101,8 +103,9 @@ def generate_from_dna_sequence(sequence): | |||
| 101 | 103 | ||
| 102 | ## Generating sine wave | 104 | ## Generating sine wave |
| 103 | 105 | ||
| 104 | Because we are essentially creating a long stream of notes we will be appending | 106 | Because we are essentially creating a long stream of notes we will be appending |
| 105 | sine notes to a global array we will later use for creating a WAV file out of it. | 107 | sine notes to a global array we will later use for creating a WAV file out of |
| 108 | it. | ||
| 106 | 109 | ||
| 107 | ```python | 110 | ```python |
| 108 | import math | 111 | import math |
| @@ -118,7 +121,7 @@ def append_sinewave(freq=440.0, duration_milliseconds=500, volume=1.0): | |||
| 118 | return | 121 | return |
| 119 | ``` | 122 | ``` |
| 120 | 123 | ||
| 121 | The sine wave generated here is the standard beep. If you want something more | 124 | The sine wave generated here is the standard beep. If you want something more |
| 122 | aggressive, you could try a square or saw tooth waveform. | 125 | aggressive, you could try a square or saw tooth waveform. |
| 123 | 126 | ||
| 124 | ## Generating a WAV file from accumulated sine waves | 127 | ## Generating a WAV file from accumulated sine waves |
| @@ -144,13 +147,13 @@ def save_wav(file_name): | |||
| 144 | wav_file.close() | 147 | wav_file.close() |
| 145 | ``` | 148 | ``` |
| 146 | 149 | ||
| 147 | 44100 is the industry standard sample rate - CD quality. If you need to save | 150 | 44100 is the industry standard sample rate - CD quality. If you need to save on |
| 148 | on file size, you can adjust it downwards. The standard for low quality is, | 151 | file size, you can adjust it downwards. The standard for low quality is, 8000 or |
| 149 | 8000 or 8kHz. | 152 | 8kHz. |
| 150 | 153 | ||
| 151 | WAV files here are using short, 16 bit, signed integers for the sample size. | 154 | WAV files here are using short, 16 bit, signed integers for the sample size. |
| 152 | So, we multiply the floating-point data we have by 32767, the maximum value | 155 | So, we multiply the floating-point data we have by 32767, the maximum value for |
| 153 | for a short integer. | 156 | a short integer. |
| 154 | 157 | ||
| 155 | > It is theoretically possible to use the floating point -1.0 to 1.0 data | 158 | > It is theoretically possible to use the floating point -1.0 to 1.0 data |
| 156 | > directly in a WAV file, but not obvious how to do that using the wave module | 159 | > directly in a WAV file, but not obvious how to do that using the wave module |
| @@ -159,8 +162,9 @@ for a short integer. | |||
| 159 | ## Generating Spectograms | 162 | ## Generating Spectograms |
| 160 | 163 | ||
| 161 | I have tried two methods of doing this and both were just fine. I however opted | 164 | I have tried two methods of doing this and both were just fine. I however opted |
| 162 | out to use the [SoX - Sound eXchange, the Swiss Army knife of audio manipulation](https://linux.die.net/man/1/sox) | 165 | out to use the [SoX - Sound eXchange, the Swiss Army knife of audio |
| 163 | one because it didn't require anything else. | 166 | manipulation](https://linux.die.net/man/1/sox) one because it didn't require |
| 167 | anything else. | ||
| 164 | 168 | ||
| 165 | ```shell | 169 | ```shell |
| 166 | sox output.wav -n spectrogram -o spectrogram.png | 170 | sox output.wav -n spectrogram -o spectrogram.png |
| @@ -174,8 +178,9 @@ An example spectrogram of Ludwig van Beethoven Symphony No. 6 First movement. | |||
| 174 | 178 | ||
| 175 |  | 179 |  |
| 176 | 180 | ||
| 177 | The other option could also be in combination with [gnuplot](http://www.gnuplot.info/). | 181 | The other option could also be in combination with |
| 178 | This would require an intermediary step, however. | 182 | [gnuplot](http://www.gnuplot.info/). This would require an intermediary step, |
| 183 | however. | ||
| 179 | 184 | ||
| 180 | ```shell | 185 | ```shell |
| 181 | sox output.wav audio.dat | 186 | sox output.wav audio.dat |
| @@ -183,7 +188,8 @@ tail -n+3 audio.dat > audio_only.dat | |||
| 183 | gnuplot audio.gpi | 188 | gnuplot audio.gpi |
| 184 | ``` | 189 | ``` |
| 185 | 190 | ||
| 186 | And input file `audio.gpi` that would be passed to gnuplot looks something like this. | 191 | And input file `audio.gpi` that would be passed to gnuplot looks something like |
| 192 | this. | ||
| 187 | 193 | ||
| 188 | ``` | 194 | ``` |
| 189 | # set output format and size | 195 | # set output format and size |
| @@ -214,9 +220,9 @@ plot "audio_only.dat" with lines lt rgb 'red' | |||
| 214 | 220 | ||
| 215 | ## Pre-generated sequences | 221 | ## Pre-generated sequences |
| 216 | 222 | ||
| 217 | What I did was take interesting parts from an animal's genome and feed it to a | 223 | What I did was take interesting parts from an animal's genome and feed it to a |
| 218 | tone generator script. This then generated a WAV file and I converted those to | 224 | tone generator script. This then generated a WAV file and I converted those to |
| 219 | MP3, so they can be played in a browser. The last step was creating a | 225 | MP3, so they can be played in a browser. The last step was creating a |
| 220 | spectrogram based on a WAV file. | 226 | spectrogram based on a WAV file. |
| 221 | 227 | ||
| 222 | ### Niels Bohr quote | 228 | ### Niels Bohr quote |
| @@ -229,8 +235,9 @@ spectrogram based on a WAV file. | |||
| 229 | 235 | ||
| 230 | ### Mouse | 236 | ### Mouse |
| 231 | 237 | ||
| 232 | This is part of a mouse genome `Mus_musculus.GRCm39.dna.nonchromosomal`. | 238 | This is part of a mouse genome `Mus_musculus.GRCm39.dna.nonchromosomal`. You |
| 233 | You can get [genom data here](http://ftp.ensembl.org/pub/release-106/fasta/mus_musculus/dna/). | 239 | can get [genom data |
| 240 | here](http://ftp.ensembl.org/pub/release-106/fasta/mus_musculus/dna/). | ||
| 234 | 241 | ||
| 235 | <audio controls> | 242 | <audio controls> |
| 236 | <source src="/assets/dna-synthesized/mouse/out.mp3" type="audio/mpeg"> | 243 | <source src="/assets/dna-synthesized/mouse/out.mp3" type="audio/mpeg"> |
| @@ -240,8 +247,9 @@ You can get [genom data here](http://ftp.ensembl.org/pub/release-106/fasta/mus_m | |||
| 240 | 247 | ||
| 241 | ### Bison | 248 | ### Bison |
| 242 | 249 | ||
| 243 | This is part of a bison genome `Bison_bison_bison.Bison_UMD1.0.cdna`. | 250 | This is part of a bison genome `Bison_bison_bison.Bison_UMD1.0.cdna`. You can |
| 244 | You can get [genom data here](http://ftp.ensembl.org/pub/release-106/fasta/bison_bison_bison/cdna/). | 251 | get [genom data |
| 252 | here](http://ftp.ensembl.org/pub/release-106/fasta/bison_bison_bison/cdna/). | ||
| 245 | 253 | ||
| 246 | <audio controls> | 254 | <audio controls> |
| 247 | <source src="/assets/dna-synthesized/bison/out.mp3" type="audio/mpeg"> | 255 | <source src="/assets/dna-synthesized/bison/out.mp3" type="audio/mpeg"> |
| @@ -251,8 +259,9 @@ You can get [genom data here](http://ftp.ensembl.org/pub/release-106/fasta/bison | |||
| 251 | 259 | ||
| 252 | ### Taurus | 260 | ### Taurus |
| 253 | 261 | ||
| 254 | This is part of a taurus genome `Bos_taurus.ARS-UCD1.2.cdna`. | 262 | This is part of a taurus genome `Bos_taurus.ARS-UCD1.2.cdna`. You can get |
| 255 | You can get [genom data here](http://ftp.ensembl.org/pub/release-106/fasta/bos_taurus/cdna/). | 263 | [genom data |
| 264 | here](http://ftp.ensembl.org/pub/release-106/fasta/bos_taurus/cdna/). | ||
| 256 | 265 | ||
| 257 | <audio controls> | 266 | <audio controls> |
| 258 | <source src="/assets/dna-synthesized/taurus/out.mp3" type="audio/mpeg"> | 267 | <source src="/assets/dna-synthesized/taurus/out.mp3" type="audio/mpeg"> |
| @@ -262,14 +271,14 @@ You can get [genom data here](http://ftp.ensembl.org/pub/release-106/fasta/bos_t | |||
| 262 | 271 | ||
| 263 | ## Making a drummer out of a DNA sequence | 272 | ## Making a drummer out of a DNA sequence |
| 264 | 273 | ||
| 265 | To make things even more interesting, I decided to send this data via MIDI to | 274 | To make things even more interesting, I decided to send this data via MIDI to my |
| 266 | my [Elektron Model:Samples](https://www.elektron.se/en/model-samples). This is | 275 | [Elektron Model:Samples](https://www.elektron.se/en/model-samples). This is a |
| 267 | a really cool piece of equipment that supports MIDI in via USB and 3.5 mm | 276 | really cool piece of equipment that supports MIDI in via USB and 3.5 mm audio |
| 268 | audio jack. | 277 | jack. |
| 269 | 278 | ||
| 270 | Elektron is connected to my MacBook via USB cable and audio out is patched to | 279 | Elektron is connected to my MacBook via USB cable and audio out is patched to a |
| 271 | a Sony Bluetooth speaker I have that supports 3.5 mm audio in. Elektron | 280 | Sony Bluetooth speaker I have that supports 3.5 mm audio in. Elektron doesn't |
| 272 | doesn't have internal speakers. | 281 | have internal speakers. |
| 273 | 282 | ||
| 274 |  | 283 |  |
| 275 | 284 | ||
| @@ -277,9 +286,9 @@ doesn't have internal speakers. | |||
| 277 | 286 | ||
| 278 |  | 287 |  |
| 279 | 288 | ||
| 280 | For communicating with Elektron, I choose `pygame` Python module that has MIDI | 289 | For communicating with Elektron, I choose `pygame` Python module that has MIDI |
| 281 | built in. With this, it was rather simple to send notes to the device. All I | 290 | built in. With this, it was rather simple to send notes to the device. All I did |
| 282 | did was map MIDI notes to the actual Nucleotides. | 291 | was map MIDI notes to the actual Nucleotides. |
| 283 | 292 | ||
| 284 | Before all of this I also checked Audio MIDI Setup app under MacOS and checked | 293 | Before all of this I also checked Audio MIDI Setup app under MacOS and checked |
| 285 | MIDI Studio by pressing ⌘-2. | 294 | MIDI Studio by pressing ⌘-2. |
| @@ -329,20 +338,21 @@ pygame.midi.quit() | |||
| 329 | <video src="/assets/dna-synthesized/elektron/elektron.mp4" controls></video> | 338 | <video src="/assets/dna-synthesized/elektron/elektron.mp4" controls></video> |
| 330 | 339 | ||
| 331 | All of this could be made much more interesting if I choose different | 340 | All of this could be made much more interesting if I choose different |
| 332 | instruments for different Nucleotides, or doing more funky stuff with Elektron. | 341 | instruments for different Nucleotides, or doing more funky stuff with Elektron. |
| 333 | But for now, this should be enough. It is just a proof of concept. Something | 342 | But for now, this should be enough. It is just a proof of concept. Something to |
| 334 | to play around with. | 343 | play around with. |
| 335 | 344 | ||
| 336 | ## Going even further | 345 | ## Going even further |
| 337 | 346 | ||
| 338 | As you probably notice, the end results are quite similar to each other. This | 347 | As you probably notice, the end results are quite similar to each other. This is |
| 339 | is to be expected because we are operating only with 4 notes essentially. What | 348 | to be expected because we are operating only with 4 notes essentially. What |
| 340 | could make this more interesting is using something like [Supercollider](https://supercollider.github.io/) | 349 | could make this more interesting is using something like |
| 341 | to create more interesting sounds. By transposing notes or using effects based | 350 | [Supercollider](https://supercollider.github.io/) to create more interesting |
| 342 | on repeated data in a sequence. Possibilities are endless. | 351 | sounds. By transposing notes or using effects based on repeated data in a |
| 352 | sequence. Possibilities are endless. | ||
| 343 | 353 | ||
| 344 | It is really astonishing what can be achieved with a little bit of code and an | 354 | It is really astonishing what can be achieved with a little bit of code and an |
| 345 | idea. I could see this becoming an interesting background soundscape instrument | 355 | idea. I could see this becoming an interesting background soundscape instrument |
| 346 | if done properly. It could replace random note generator with something more | 356 | if done properly. It could replace random note generator with something more |
| 347 | intriguing, biological, natural. | 357 | intriguing, biological, natural. |
| 348 | 358 | ||
| @@ -351,4 +361,3 @@ music of nature. Even though it's quite the same, it's also quite different. | |||
| 351 | The subtle differences on repeat kind of creates music on its own. Makes you | 361 | The subtle differences on repeat kind of creates music on its own. Makes you |
| 352 | wonder. It kind of puts Occam’s Razor in its place. Nature for sure loves to | 362 | wonder. It kind of puts Occam’s Razor in its place. Nature for sure loves to |
| 353 | make things as energy efficient as possible. | 363 | make things as energy efficient as possible. |
| 354 | |||
diff --git a/content/posts/2022-08-13-algae-spotted-on-river-sava.md b/content/posts/2022-08-13-algae-spotted-on-river-sava.md index faa2df1..e82e364 100644 --- a/content/posts/2022-08-13-algae-spotted-on-river-sava.md +++ b/content/posts/2022-08-13-algae-spotted-on-river-sava.md | |||
| @@ -5,10 +5,10 @@ date: 2022-08-13T12:00:00+02:00 | |||
| 5 | draft: false | 5 | draft: false |
| 6 | --- | 6 | --- |
| 7 | 7 | ||
| 8 | This is a bit of a different post than I usually write, but quite interesting | 8 | This is a bit of a different post than I usually write, but quite interesting |
| 9 | one to me. River Sava has plenty of hydropower plants located down the stream. | 9 | one to me. River Sava has plenty of hydropower plants located down the stream. |
| 10 | This makes regulating the strength of a current easier than normally. Because | 10 | This makes regulating the strength of a current easier than normally. Because of |
| 11 | of lower stream strength and high temperatures, algae has formed on the river. | 11 | lower stream strength and high temperatures, algae has formed on the river. |
| 12 | This is the first time I've seen something like this in my whole life. | 12 | This is the first time I've seen something like this in my whole life. |
| 13 | 13 | ||
| 14 | Below are some photographs taken from a DJI drone capturing the event. | 14 | Below are some photographs taken from a DJI drone capturing the event. |
| @@ -25,6 +25,6 @@ Below are some photographs taken from a DJI drone capturing the event. | |||
| 25 | 25 | ||
| 26 |  | 26 |  |
| 27 | 27 | ||
| 28 | I will try to get more photos of this in the future days and if something | 28 | I will try to get more photos of this in the future days and if something |
| 29 | intriguing shows up will post it again on the blog. | 29 | intriguing shows up will post it again on the blog. |
| 30 | 30 | ||
diff --git a/content/posts/2022-10-06-state-of-web-technologies-in-year-2022.md b/content/posts/2022-10-06-state-of-web-technologies-in-year-2022.md index 120dcae..78595fa 100644 --- a/content/posts/2022-10-06-state-of-web-technologies-in-year-2022.md +++ b/content/posts/2022-10-06-state-of-web-technologies-in-year-2022.md | |||
| @@ -7,23 +7,23 @@ draft: false | |||
| 7 | 7 | ||
| 8 | ## Initial thoughts | 8 | ## Initial thoughts |
| 9 | 9 | ||
| 10 | *This post is a critique on the current state of web development. It is an | 10 | *This post is a critique on the current state of web development. It is an |
| 11 | opinionated post! I will learn more about this in the future, and probably | 11 | opinionated post! I will learn more about this in the future, and probably |
| 12 | slightly change my mind about some of the things I criticize.* | 12 | slightly change my mind about some of the things I criticize.* |
| 13 | 13 | ||
| 14 | I have started working on a hobby project about two weeks ago, and I wanted to | 14 | I have started working on a hobby project about two weeks ago, and I wanted to |
| 15 | use that situation as a learning one. Trying new things, new technologies, new | 15 | use that situation as a learning one. Trying new things, new technologies, new |
| 16 | tools. I always considered myself to be an adventurous person when it comes to | 16 | tools. I always considered myself to be an adventurous person when it comes to |
| 17 | technology. I never shy away from trying new languages, new operating systems | 17 | technology. I never shy away from trying new languages, new operating systems |
| 18 | etc. Likewise, I find the whole experience satisfying, and it tickles that part | 18 | etc. Likewise, I find the whole experience satisfying, and it tickles that part |
| 19 | of my brain that finds discovery the highest of the mountains to climb. | 19 | of my brain that finds discovery the highest of the mountains to climb. |
| 20 | 20 | ||
| 21 | What I always wanted to make was a coding game, that you would play in a | 21 | What I always wanted to make was a coding game, that you would play in a browser |
| 22 | browser (just to eliminate building binaries for each operating system) where | 22 | (just to eliminate building binaries for each operating system) where you would |
| 23 | you would level up your character and go into these scriptable battles. You | 23 | level up your character and go into these scriptable battles. You know, RPG |
| 24 | know, RPG elements. | 24 | elements. |
| 25 | 25 | ||
| 26 | So, the natural way to go would be some sort of SPA (single page application) | 26 | So, the natural way to go would be some sort of SPA (single page application) |
| 27 | with basic routing and some state management. Nothing crazy. | 27 | with basic routing and some state management. Nothing crazy. |
| 28 | 28 | ||
| 29 | > **Before we move on**, I have to be transparent. Take my views on this with | 29 | > **Before we move on**, I have to be transparent. Take my views on this with |
| @@ -31,92 +31,92 @@ with basic routing and some state management. Nothing crazy. | |||
| 31 | > and my knowledge is full of gaps. This is my experience using some of these | 31 | > and my knowledge is full of gaps. This is my experience using some of these |
| 32 | > products for the first time or in a limited capacity. | 32 | > products for the first time or in a limited capacity. |
| 33 | 33 | ||
| 34 | Having this out of the way, I got myself a fresh pot of coffee and down the | 34 | Having this out of the way, I got myself a fresh pot of coffee and down the |
| 35 | rabbit hole I went. | 35 | rabbit hole I went. |
| 36 | 36 | ||
| 37 | ## Giving React JS a spin | 37 | ## Giving React JS a spin |
| 38 | 38 | ||
| 39 | I first tried [React JS](https://reactjs.org/). I kind of like it. Furthermore, | 39 | I first tried [React JS](https://reactjs.org/). I kind of like it. Furthermore, |
| 40 | I have worked with libraries like this in the past and also wrote a couple of | 40 | I have worked with libraries like this in the past and also wrote a couple of |
| 41 | them (nothing compared to that level), but I had the basic understanding of | 41 | them (nothing compared to that level), but I had the basic understanding of what |
| 42 | what was going on. I rolled up a project quickly and had basic things done in | 42 | was going on. I rolled up a project quickly and had basic things done in a |
| 43 | a matter of two hours, which was impressive. | 43 | matter of two hours, which was impressive. |
| 44 | 44 | ||
| 45 | I prefer using [Tailwind CSS](https://tailwindcss.com/) for my styling | 45 | I prefer using [Tailwind CSS](https://tailwindcss.com/) for my styling |
| 46 | pleasures, and integrating that was also a painless experience. It was actually | 46 | pleasures, and integrating that was also a painless experience. It was actually |
| 47 | nice to see that some things got better with time. In about 2 minutes I got | 47 | nice to see that some things got better with time. In about 2 minutes I got |
| 48 | Tailwind working, and I was able to use classes at my disposal. All that | 48 | Tailwind working, and I was able to use classes at my disposal. All that |
| 49 | `postcss` stuff was taken care of by adding a couple of things in config files | 49 | `postcss` stuff was taken care of by adding a couple of things in config files |
| 50 | (all described really well in their documentation). | 50 | (all described really well in their documentation). |
| 51 | 51 | ||
| 52 | It is not that different from Vue which I have had more encounters with in the | 52 | It is not that different from Vue which I have had more encounters with in the |
| 53 | past People will probably call me a lunatic for saying this. But you know, it | 53 | past People will probably call me a lunatic for saying this. But you know, it is |
| 54 | is the truth. Same same, but different. I still believe that using libraries | 54 | the truth. Same same, but different. I still believe that using libraries like |
| 55 | like this is beneficial. I am not a JavaScript purist. They all have their | 55 | this is beneficial. I am not a JavaScript purist. They all have their quirks, |
| 56 | quirks, but at the end of the day, I truly believe it’s worth it. | 56 | but at the end of the day, I truly believe it’s worth it. |
| 57 | 57 | ||
| 58 | ## Bundlers and Transpilers | 58 | ## Bundlers and Transpilers |
| 59 | 59 | ||
| 60 | I still reject calling [Typescript](https://www.typescriptlang.org/) to | 60 | I still reject calling [Typescript](https://www.typescriptlang.org/) to |
| 61 | [JavaScript](https://www.javascript.com/) conversion a "compilation process". | 61 | [JavaScript](https://www.javascript.com/) conversion a "compilation process". I |
| 62 | I call them [transpilers](https://devopedia.org/transpiler), and I don’t care! 😈 | 62 | call them [transpilers](https://devopedia.org/transpiler), and I don’t care! 😈 |
| 63 | 63 | ||
| 64 | And if you want to fight this, take a look at this little chart and be mad at it! | 64 | And if you want to fight this, take a look at this little chart and be mad at |
| 65 | it! | ||
| 65 | 66 | ||
| 66 |  | 67 |  |
| 67 | 68 | ||
| 68 | The first one that I ever used was [webpack](https://webpack.js.org/), and it | 69 | The first one that I ever used was [webpack](https://webpack.js.org/), and it |
| 69 | was an absolute horrific experience. Saying this, it is an absolutely | 70 | was an absolute horrific experience. Saying this, it is an absolutely fantastic |
| 70 | fantastic tool. I felt more like a config editor than actually a programmer. | 71 | tool. I felt more like a config editor than actually a programmer. To be fair, |
| 71 | To be fair, I am a huge fan of [make](https://www.gnu.org/software/make/), | 72 | I am a huge fan of [make](https://www.gnu.org/software/make/), and you can do as |
| 72 | and you can do as you wish with this information. I like my build systems | 73 | you wish with this information. I like my build systems simple. |
| 73 | simple. | ||
| 74 | 74 | ||
| 75 | Also, isn’t it interesting that we need something like [Babel](https://babeljs.io/) | 75 | Also, isn’t it interesting that we need something like |
| 76 | to make JavaScript code work in a browser that has only one client side | 76 | [Babel](https://babeljs.io/) to make JavaScript code work in a browser that has |
| 77 | scripting available, which is by no accident also JavaScript. Why? I know | 77 | only one client side scripting available, which is by no accident also |
| 78 | why it’s needed, but seriously, why. | 78 | JavaScript. Why? I know why it’s needed, but seriously, why. |
| 79 | 79 | ||
| 80 | I haven’t used Babel for years now. Or if I did, it was packaged together by | 80 | I haven’t used Babel for years now. Or if I did, it was packaged together by |
| 81 | some other bundler thingy. Which does not make things better, but at least | 81 | some other bundler thingy. Which does not make things better, but at least I |
| 82 | I didn’t need to worry about it. | 82 | didn’t need to worry about it. |
| 83 | 83 | ||
| 84 | I really don’t like complicated build systems. I really don’t like abstracting | 84 | I really don’t like complicated build systems. I really don’t like abstracting |
| 85 | code and making things appear magical. The older I get, the more I appreciate | 85 | code and making things appear magical. The older I get, the more I appreciate |
| 86 | clear and clean, expressive code. No one-liners, if possible. | 86 | clear and clean, expressive code. No one-liners, if possible. |
| 87 | 87 | ||
| 88 | But I have to give props to [Vite](https://vitejs.dev/)! This was one of the | 88 | But I have to give props to [Vite](https://vitejs.dev/)! This was one of the |
| 89 | best developer experiences I have ever had. Granted, it still has magical | 89 | best developer experiences I have ever had. Granted, it still has magical |
| 90 | properties. And yes, it still is a bundler and abstracts things to the nth | 90 | properties. And yes, it still is a bundler and abstracts things to the nth |
| 91 | degree. But at least it didn’t force me to configure 700 lines of JSON. And | 91 | degree. But at least it didn’t force me to configure 700 lines of JSON. And I |
| 92 | I know that this makes me a hypocrite. You can’t have it all. Nonetheless, | 92 | know that this makes me a hypocrite. You can’t have it all. Nonetheless, my |
| 93 | my reasoning here is, if using bundlers is inevitable, then at least they | 93 | reasoning here is, if using bundlers is inevitable, then at least they should |
| 94 | should provide an excellent developer experience. | 94 | provide an excellent developer experience. |
| 95 | 95 | ||
| 96 | I also noticed that now the catch-all phrase is “blazingly fast” and | 96 | I also noticed that now the catch-all phrase is “blazingly fast” and “lightning |
| 97 | “lightning fast” and “next generation” and stuff like that. I mean, yeah, | 97 | fast” and “next generation” and stuff like that. I mean, yeah, tools should get |
| 98 | tools should get faster with time. But saying that starting a project now takes | 98 | faster with time. But saying that starting a project now takes 2 seconds instead |
| 99 | 2 seconds instead of 20 seconds is something that is a break it or make it kind | 99 | of 20 seconds is something that is a break it or make it kind of a deal is |
| 100 | of a deal is ridiculous. I don’t mind waiting a couple of seconds every couple | 100 | ridiculous. I don’t mind waiting a couple of seconds every couple of days. I |
| 101 | of days. I also don’t create 700 projects every day, and also who does? This | 101 | also don’t create 700 projects every day, and also who does? This argument has |
| 102 | argument has no bite. All I want is a decent reload time (~100ms is more than | 102 | no bite. All I want is a decent reload time (~100ms is more than good enough for |
| 103 | good enough for me) and that is it. | 103 | me) and that is it. |
| 104 | 104 | ||
| 105 | You don’t need to sell me benefits if I only get them when I start a fresh | 105 | You don’t need to sell me benefits if I only get them when I start a fresh |
| 106 | project, and then try to convince me that this is somehow changing the fate | 106 | project, and then try to convince me that this is somehow changing the fate of |
| 107 | of the universe. First of all, it is not. And second, if this is your only | 107 | the universe. First of all, it is not. And second, if this is your only argument |
| 108 | argument for your tool, I would advise you to maybe re-focus your efforts to | 108 | for your tool, I would advise you to maybe re-focus your efforts to something |
| 109 | something else. Vite says that startup times are really fast. And if that | 109 | else. Vite says that startup times are really fast. And if that would be the |
| 110 | would be the only thing differentiating it from other tools, I would ignore | 110 | only thing differentiating it from other tools, I would ignore it. But it has |
| 111 | it. But it has some really compelling features like | 111 | some really compelling features like [Hot Module |
| 112 | [Hot Module Replacement](https://www.geeksforgeeks.org/reactjs-hot-module-replacement/) | 112 | Replacement](https://www.geeksforgeeks.org/reactjs-hot-module-replacement/) that |
| 113 | that really works well. It was a joy to use. | 113 | really works well. It was a joy to use. |
| 114 | 114 | ||
| 115 | So, I will be definitely using Vite in the future. | 115 | So, I will be definitely using Vite in the future. |
| 116 | 116 | ||
| 117 | ## Jam Stack, Mach Stack no snack | 117 | ## Jam Stack, Mach Stack no snack |
| 118 | 118 | ||
| 119 | Let's get a couple of the acronyms out of the way, so we all know what we are | 119 | Let's get a couple of the acronyms out of the way, so we all know what we are |
| 120 | talking about: | 120 | talking about: |
| 121 | 121 | ||
| 122 | - Jam Stack - JavaScript, API and Markup | 122 | - Jam Stack - JavaScript, API and Markup |
| @@ -124,74 +124,75 @@ talking about: | |||
| 124 | 124 | ||
| 125 | It is so hard to follow all these new trendy things happening around you, that | 125 | It is so hard to follow all these new trendy things happening around you, that |
| 126 | it makes you have a massive **FOMO** all the time. But on the other hand, you | 126 | it makes you have a massive **FOMO** all the time. But on the other hand, you |
| 127 | also don’t want to be that old fart that doesn’t move with the times and still | 127 | also don’t want to be that old fart that doesn’t move with the times and still |
| 128 | writes his trusty jQuery code while listening to Blink 182 All the small things | 128 | writes his trusty jQuery code while listening to Blink 182 All the small things |
| 129 | on full blast. It’s a good song, don’t get me wrong, but there are other songs | 129 | on full blast. It’s a good song, don’t get me wrong, but there are other songs |
| 130 | out there. | 130 | out there. |
| 131 | 131 | ||
| 132 | I have to admit. [Vercel](https://vercel.com/) is really cool! Love the | 132 | I have to admit. [Vercel](https://vercel.com/) is really cool! Love the |
| 133 | simplicity of the service. You could compare it to [Netlify](https://www.netlify.com/). | 133 | simplicity of the service. You could compare it to |
| 134 | I haven’t tried Netlify extensively, but from a couple of experimental | 134 | [Netlify](https://www.netlify.com/). I haven’t tried Netlify extensively, but |
| 135 | deployments I still prefer Vercel. It is much more streamlined, but maybe this | 135 | from a couple of experimental deployments I still prefer Vercel. It is much more |
| 136 | is bias in me. I really like Vercel’s Analytics, which give you a | 136 | streamlined, but maybe this is bias in me. I really like Vercel’s Analytics, |
| 137 | [Core Web Vitals report](https://web.dev/vitals/) in their admin console. Kind | 137 | which give you a [Core Web Vitals report](https://web.dev/vitals/) in their |
| 138 | of cool, I’m not going to lie. | 138 | admin console. Kind of cool, I’m not going to lie. |
| 139 | 139 | ||
| 140 | This whole idea about frontend and backend merging into [SSR (server-side rendering)](https://www.debugbear.com/blog/server-side-rendering) | 140 | This whole idea about frontend and backend merging into [SSR (server-side |
| 141 | looks so good on paper. It almost doesn’t come with any major flaws. | 141 | rendering)](https://www.debugbear.com/blog/server-side-rendering) looks so good |
| 142 | on paper. It almost doesn’t come with any major flaws. | ||
| 142 | 143 | ||
| 143 | But when it comes to the actual implementation, there is much to be desired. | 144 | But when it comes to the actual implementation, there is much to be desired. |
| 144 | I’m going to lump [Next.js](https://nextjs.org/) and [Nuxt.js](https://nuxtjs.org/) | 145 | I’m going to lump [Next.js](https://nextjs.org/) and |
| 145 | together because they are essentially the same thing, just a different library. | 146 | [Nuxt.js](https://nuxtjs.org/) together because they are essentially the same |
| 147 | thing, just a different library. | ||
| 146 | 148 | ||
| 147 | Now comes the reality. Mixing backend and frontend in this manner creates this | 149 | Now comes the reality. Mixing backend and frontend in this manner creates this |
| 148 | weird mental model where you kind of rely on magical properties of these | 150 | weird mental model where you kind of rely on magical properties of these |
| 149 | libraries. You relinquish control over to them for better developer experience. | 151 | libraries. You relinquish control over to them for better developer experience. |
| 150 | But is that really true? Initially, I was so stoked about it. However, the | 152 | But is that really true? Initially, I was so stoked about it. However, the more |
| 151 | more I used them, the more I felt uncomfortable. I felt dirty, actually. Maybe | 153 | I used them, the more I felt uncomfortable. I felt dirty, actually. Maybe this |
| 152 | this is because I come from old ways of doing things where you control every | 154 | is because I come from old ways of doing things where you control every step of |
| 153 | step of request, and allowing something to hijack it feels like blasphemy. | 155 | request, and allowing something to hijack it feels like blasphemy. |
| 154 | 156 | ||
| 155 | More than that, some pretty significant technical issues arose from this. How | 157 | More than that, some pretty significant technical issues arose from this. How do |
| 156 | do you do JWT token authentication? You put it in `api` folder and then do some | 158 | you do JWT token authentication? You put it in `api` folder and then do some |
| 157 | fetching and storing into local state management. But doing this also requires | 159 | fetching and storing into local state management. But doing this also requires |
| 158 | some tinkering with await/async stuff on the React/Vue side of things. And then | 160 | some tinkering with await/async stuff on the React/Vue side of things. And then |
| 159 | you need to write middleware for it. And the more I look at it, the more I see | 161 | you need to write middleware for it. And the more I look at it, the more I see |
| 160 | that this whole thing was not meant to be used like this, and it all feels and | 162 | that this whole thing was not meant to be used like this, and it all feels and |
| 161 | looks like a huge hack. | 163 | looks like a huge hack. |
| 162 | 164 | ||
| 163 | The issue I have with this is that they over-promise and under-deliver. They | 165 | The issue I have with this is that they over-promise and under-deliver. They |
| 164 | want to be an all-in-one replacement for everything, and they don’t deliver | 166 | want to be an all-in-one replacement for everything, and they don’t deliver on |
| 165 | on this promise. And how could they?! We have to be fair. It is an impossible | 167 | this promise. And how could they?! We have to be fair. It is an impossible task. |
| 166 | task. | ||
| 167 | 168 | ||
| 168 | They sell you [NoOps](https://www.geeksforgeeks.org/overview-of-noops/), but | 169 | They sell you [NoOps](https://www.geeksforgeeks.org/overview-of-noops/), but |
| 169 | when you need to accomplish something a little bit more out of the scope of | 170 | when you need to accomplish something a little bit more out of the scope of |
| 170 | Hello World, you have to make hacky decisions to make it work. And having a | 171 | Hello World, you have to make hacky decisions to make it work. And having a |
| 171 | deployment strategy that relies on many moving parts is never a good idea. | 172 | deployment strategy that relies on many moving parts is never a good idea. |
| 172 | Abstracting too much is usually a sign of bad architecture. | 173 | Abstracting too much is usually a sign of bad architecture. |
| 173 | 174 | ||
| 174 | Lately, this has become a huge trend that will for sure bite us in the future. | 175 | Lately, this has become a huge trend that will for sure bite us in the future. |
| 175 | And let’s not get it twisted. By doing this, PaaS providers like | 176 | And let’s not get it twisted. By doing this, PaaS providers like |
| 176 | [AWS](https://aws.amazon.com/), [GCS](https://cloud.google.com/), etc. obscure | 177 | [AWS](https://aws.amazon.com/), [GCS](https://cloud.google.com/), etc. obscure |
| 177 | their billing, and you end up paying more than you really should. And even if | 178 | their billing, and you end up paying more than you really should. And even if |
| 178 | that is not an issue, it comes down to the principle of things. AWS is known | 179 | that is not an issue, it comes down to the principle of things. AWS is known for |
| 179 | for having multiple “currencies“ inside their projects like write operations, | 180 | having multiple “currencies“ inside their projects like write operations, read |
| 180 | read operations, etc. which add up, and it creates this impossible to track | 181 | operations, etc. which add up, and it creates this impossible to track billing |
| 181 | billing scheme. It all behaves suspiciously like a pay-to-win game you could | 182 | scheme. It all behaves suspiciously like a pay-to-win game you could find on |
| 182 | find on mobile phones that scams you out of your money. | 183 | mobile phones that scams you out of your money. |
| 183 | 184 | ||
| 184 | And as far as I am concerned, the most important thing was me not coding the | 185 | And as far as I am concerned, the most important thing was me not coding the |
| 185 | functionalities for the game I want to make. I was battling libraries and | 186 | functionalities for the game I want to make. I was battling libraries and cloud |
| 186 | cloud providers. How to deploy, what settings are relevant. Bad documentation | 187 | providers. How to deploy, what settings are relevant. Bad documentation or |
| 187 | or multiple versions of achieving the same thing. You are getting bombarded | 188 | multiple versions of achieving the same thing. You are getting bombarded by all |
| 188 | by all this information, and you don’t really have any control over it. | 189 | this information, and you don’t really have any control over it. |
| 189 | Production-ready code becomes a joke, essentially. Especially if you tend to | 190 | Production-ready code becomes a joke, essentially. Especially if you tend to |
| 190 | work on that project for a prolonged period of time. | 191 | work on that project for a prolonged period of time. |
| 191 | 192 | ||
| 192 | All of these options end up creating a fatigue. What to choose, what not to | 193 | All of these options end up creating a fatigue. What to choose, what not to |
| 193 | choose. Unnecessary worrying about if the stack will still be deemed worthy | 194 | choose. Unnecessary worrying about if the stack will still be deemed worthy in |
| 194 | in six months. There is elegance in simplicity. | 195 | six months. There is elegance in simplicity. |
| 195 | 196 | ||
| 196 | > JavaScript UI frameworks and libraries work in cycles. Every six months or | 197 | > JavaScript UI frameworks and libraries work in cycles. Every six months or |
| 197 | > so, a new one pops up, claiming that it has revolutionized UI development. | 198 | > so, a new one pops up, claiming that it has revolutionized UI development. |
| @@ -202,102 +203,101 @@ in six months. There is elegance in simplicity. | |||
| 202 | 203 | ||
| 203 |  | 204 |  |
| 204 | 205 | ||
| 205 | And this jab at these libraries and cloud providers is not done out of malice. | 206 | And this jab at these libraries and cloud providers is not done out of malice. |
| 206 | It is a real concern that I have about them. In my life, I have seen | 207 | It is a real concern that I have about them. In my life, I have seen |
| 207 | technologies come and go, but the basics always stick around. So surrendering | 208 | technologies come and go, but the basics always stick around. So surrendering |
| 208 | all the power you have to a library or a cloud provider is in my opinion a | 209 | all the power you have to a library or a cloud provider is in my opinion a |
| 209 | stupid move. | 210 | stupid move. |
| 210 | 211 | ||
| 211 | ## Tailwind CSS still rocks! | 212 | ## Tailwind CSS still rocks! |
| 212 | 213 | ||
| 213 | You know, many people say negative things about Tailwind. And after a lot of | 214 | You know, many people say negative things about Tailwind. And after a lot of |
| 214 | deliberation, I came to the conclusion that Tailwind is good for two types of | 215 | deliberation, I came to the conclusion that Tailwind is good for two types of |
| 215 | developers. Tailwind is good for a complete noob or a senior developer. A | 216 | developers. Tailwind is good for a complete noob or a senior developer. A |
| 216 | complete noob doesn’t really care about inner workings of CSS, and a senior | 217 | complete noob doesn’t really care about inner workings of CSS, and a senior |
| 217 | developer also doesn’t care about CSS. Well, at least, not anymore. And | 218 | developer also doesn’t care about CSS. Well, at least, not anymore. And |
| 218 | developers in between usually have the biggest issues with it. Not always of | 219 | developers in between usually have the biggest issues with it. Not always of |
| 219 | course, but in a lot of cases. | 220 | course, but in a lot of cases. |
| 220 | 221 | ||
| 221 | I like the creature comforts of Tailwind. Being utility first would make me | 222 | I like the creature comforts of Tailwind. Being utility first would make me |
| 222 | argue that it is actually more similar to [Sass](https://sass-lang.com/) or | 223 | argue that it is actually more similar to [Sass](https://sass-lang.com/) or |
| 223 | [Less](https://lesscss.org/) than something like Bootstrap. Not technically, | 224 | [Less](https://lesscss.org/) than something like Bootstrap. Not technically, but |
| 224 | but ideologically. After I started using it, I never looked back. I use it | 225 | ideologically. After I started using it, I never looked back. I use it every |
| 225 | every time I need to do something web related. | 226 | time I need to do something web related. |
| 226 | 227 | ||
| 227 | Writing CSS for general things feels like going several steps back. Instead of | 228 | Writing CSS for general things feels like going several steps back. Instead of |
| 228 | focusing on what you are actually trying to achieve, you focus on notations | 229 | focusing on what you are actually trying to achieve, you focus on notations like |
| 229 | like [BEM](https://en.bem.info/methodology/css/), code structuring, optimizing | 230 | [BEM](https://en.bem.info/methodology/css/), code structuring, optimizing HTML |
| 230 | HTML size. Just doing things that make 0.1% difference. You know that saying: | 231 | size. Just doing things that make 0.1% difference. You know that saying: Early |
| 231 | Early optimization is the root of all evil. Exactly that. | 232 | optimization is the root of all evil. Exactly that. |
| 232 | 233 | ||
| 233 | I am also not saying that Tailwind is the cure for everything. Sometimes custom | 234 | I am also not saying that Tailwind is the cure for everything. Sometimes custom |
| 234 | CSS is necessary. But from what I found out in using it for almost two years | 235 | CSS is necessary. But from what I found out in using it for almost two years in |
| 235 | in a production environment (on a site getting quite a lot of traffic and | 236 | a production environment (on a site getting quite a lot of traffic and |
| 236 | constantly being changed), I can say without any reservations that Tailwind | 237 | constantly being changed), I can say without any reservations that Tailwind |
| 237 | saved our asses countless times. We would be rewriting CSS all the time without | 238 | saved our asses countless times. We would be rewriting CSS all the time without |
| 238 | it. And I don’t really think writing CSS is the best way to spend my time. | 239 | it. And I don’t really think writing CSS is the best way to spend my time. |
| 239 | 240 | ||
| 240 | I have also noticed that people who criticize Tailwind the most never actually | 241 | I have also noticed that people who criticize Tailwind the most never actually |
| 241 | used it in a real project that has a long lifetime with plenty of changes that | 242 | used it in a real project that has a long lifetime with plenty of changes that |
| 242 | will happen in the future. | 243 | will happen in the future. |
| 243 | 244 | ||
| 244 | But you know, whatever floats your boat! | 245 | But you know, whatever floats your boat! |
| 245 | 246 | ||
| 246 | ## Code maintainability | 247 | ## Code maintainability |
| 247 | 248 | ||
| 248 | Somehow, people also stopped talking about maintenance. If you constantly try | 249 | Somehow, people also stopped talking about maintenance. If you constantly try to |
| 249 | to catch the latest and greatest train, you are by that logic always trying | 250 | catch the latest and greatest train, you are by that logic always trying new |
| 250 | new things. Which is a good thing if you want to learn about technologies and | 251 | things. Which is a good thing if you want to learn about technologies and try |
| 251 | try them. But for the production environment, you have to have a stable stack | 252 | them. But for the production environment, you have to have a stable stack that |
| 252 | that doesn’t change every 6 months. | 253 | doesn’t change every 6 months. |
| 253 | 254 | ||
| 254 | You can lock dependencies for sure. Nevertheless, the hype train moves along | 255 | You can lock dependencies for sure. Nevertheless, the hype train moves along |
| 255 | anyway. And the mindset this breeds goes against locking the code. This | 256 | anyway. And the mindset this breeds goes against locking the code. This |
| 256 | bleeding-edge rolling release cycle is not helping. That is why enterprise | 257 | bleeding-edge rolling release cycle is not helping. That is why enterprise |
| 257 | solutions usually look down on these popular stacks and only do bare minimum to | 258 | solutions usually look down on these popular stacks and only do bare minimum to |
| 258 | appear hip and cool. | 259 | appear hip and cool. |
| 259 | 260 | ||
| 260 | With that said, I still think that progress is good, but should be taken with a | 261 | With that said, I still think that progress is good, but should be taken with a |
| 261 | grain of salt. If your project is something that should be built once and then | 262 | grain of salt. If your project is something that should be built once and then |
| 262 | rarely updated, going with the latest stack is a possible way to go. But, if | 263 | rarely updated, going with the latest stack is a possible way to go. But, if you |
| 263 | you are working on a project that lasts for years, you should probably approach | 264 | are working on a project that lasts for years, you should probably approach it |
| 264 | it with some level of caution. Web development is often times too volatile. | 265 | with some level of caution. Web development is often times too volatile. |
| 265 | 266 | ||
| 266 | ## Web development has a marketing issue | 267 | ## Web development has a marketing issue |
| 267 | 268 | ||
| 268 | I noticed that almost every project now has this marketing spin put on it. | 269 | I noticed that almost every project now has this marketing spin put on it. |
| 269 | Everything is blazingly fast now. I get it, they are competing for your | 270 | Everything is blazingly fast now. I get it, they are competing for your |
| 270 | attention, but what happened to just being truthful and not inflating reality. | 271 | attention, but what happened to just being truthful and not inflating reality. |
| 271 | 272 | ||
| 272 | And in order to appeal to mass market, they leave things out of their marketing | 273 | And in order to appeal to mass market, they leave things out of their marketing |
| 273 | materials. These open-source projects are now behaving more and more like | 274 | materials. These open-source projects are now behaving more and more like |
| 274 | companies do. Which is a scary thought on its self. | 275 | companies do. Which is a scary thought on its self. |
| 275 | 276 | ||
| 276 | And we are also seeing a rise in a concept of building a company in the open, | 277 | And we are also seeing a rise in a concept of building a company in the open, |
| 277 | which is a good thing, don't get me wrong. But when it is using open-source to | 278 | which is a good thing, don't get me wrong. But when it is using open-source to |
| 278 | lure people and then lock them in their ecosystem, there is where I have issues | 279 | lure people and then lock them in their ecosystem, there is where I have issues |
| 279 | with it. | 280 | with it. |
| 280 | 281 | ||
| 281 | This might be because I have been using GNU/Linux for 20 years now and have | 282 | This might be because I have been using GNU/Linux for 20 years now and have been |
| 282 | been so beholden for my success to open-source that I see issues when | 283 | so beholden for my success to open-source that I see issues when open-source is |
| 283 | open-source is being used to trick people into a false sense of security that | 284 | being used to trick people into a false sense of security that these projects |
| 284 | these projects are built in the spirit of open-source. Because there is a | 285 | are built in the spirit of open-source. Because there is a difference. They are |
| 285 | difference. They are NOT! They have a really specific goal in mind. And the | 286 | NOT! They have a really specific goal in mind. And the open-source is being used |
| 286 | open-source is being used as a delivery system. Which is in my opinion | 287 | as a delivery system. Which is in my opinion disgusting! |
| 287 | disgusting! | ||
| 288 | 288 | ||
| 289 | ## Conclusion | 289 | ## Conclusion |
| 290 | 290 | ||
| 291 | I will end my post with this. Web development is running now in circles. People | 291 | I will end my post with this. Web development is running now in circles. People |
| 292 | are discovering [RPC](https://www.tutorialspoint.com/remote-procedure-call-rpc) | 292 | are discovering [RPC](https://www.tutorialspoint.com/remote-procedure-call-rpc) |
| 293 | now and this is the now the next big thing. [GraphQL](https://graphql.org/) is | 293 | now and this is the now the next big thing. [GraphQL](https://graphql.org/) is |
| 294 | so passé. And I am so tired of it all. Of blazingly fast libraries, of all | 294 | so passé. And I am so tired of it all. Of blazingly fast libraries, of all these |
| 295 | these new technologies that are actually just a remake of old ones. Of just | 295 | new technologies that are actually just a remake of old ones. Of just the |
| 296 | the general spirit of the web. I will just use what I already know. Which worked | 296 | general spirit of the web. I will just use what I already know. Which worked 10 |
| 297 | 10 years ago and will work 10 years after this. I will adopt a couple of | 297 | years ago and will work 10 years after this. I will adopt a couple of little |
| 298 | little tools like Vite. But I will not waste my time on this anymore. | 298 | tools like Vite. But I will not waste my time on this anymore. |
| 299 | 299 | ||
| 300 | It was a good exercise to get in touch with what’s new now. Nothing really | 300 | It was a good exercise to get in touch with what’s new now. Nothing really |
| 301 | changed that much. FOMO is now cured! Now I have to get my ass back to actually | 301 | changed that much. FOMO is now cured! Now I have to get my ass back to actually |
| 302 | code and make the project that I wanted to make in the first place. | 302 | code and make the project that I wanted to make in the first place. |
| 303 | 303 | ||
diff --git a/content/posts/2022-10-16-that-sound-that-machine-makes-when-struggling.md b/content/posts/2022-10-16-that-sound-that-machine-makes-when-struggling.md index 2739764..05a8167 100644 --- a/content/posts/2022-10-16-that-sound-that-machine-makes-when-struggling.md +++ b/content/posts/2022-10-16-that-sound-that-machine-makes-when-struggling.md | |||
| @@ -5,60 +5,61 @@ date: 2022-10-16T12:00:00+02:00 | |||
| 5 | draft: false | 5 | draft: false |
| 6 | --- | 6 | --- |
| 7 | 7 | ||
| 8 | A couple of months ago, I got an idea about micro soundtracks. In this concept, | 8 | A couple of months ago, I got an idea about micro soundtracks. In this concept, |
| 9 | you are the observer, director, and audience in this tiny movies. | 9 | you are the observer, director, and audience in this tiny movies. |
| 10 | 10 | ||
| 11 | What you do is to attempt to imagine what would be happening around you based | 11 | What you do is to attempt to imagine what would be happening around you based on |
| 12 | on a title of the song and let the song help you fill the void in your story. | 12 | a title of the song and let the song help you fill the void in your story. |
| 13 | 13 | ||
| 14 | I made these songs is Logic Pro X. Every year or so I do this kind of thing | 14 | I made these songs is Logic Pro X. Every year or so I do this kind of thing and |
| 15 | and make a couple of songs similar to this. But this is the first time I am | 15 | make a couple of songs similar to this. But this is the first time I am posting |
| 16 | posting about it. | 16 | about it. |
| 17 | 17 | ||
| 18 | You can listen to the whole set on [Youtube](https://www.youtube.com/watch?v=_5oXBhSmF3c) | 18 | You can listen to the whole set on |
| 19 | or scroll down the page and there are embedded players for each song. | 19 | [Youtube](https://www.youtube.com/watch?v=_5oXBhSmF3c) or scroll down the page |
| 20 | and there are embedded players for each song. | ||
| 20 | 21 | ||
| 21 | ## A bunch of inter-dimensional people with loud clocks | 22 | ## A bunch of inter-dimensional people with loud clocks |
| 22 | 23 | ||
| 23 | A group of inter-dimensional people are going up and down the elevator with | 24 | A group of inter-dimensional people are going up and down the elevator with you |
| 24 | you while having loud clocks around their necks. Each clock ticks on a different | 25 | while having loud clocks around their necks. Each clock ticks on a different |
| 25 | frequency. A lot of other sounds are getting drawn into your dimension, | 26 | frequency. A lot of other sounds are getting drawn into your dimension, |
| 26 | resulting in a strange merging of dimensions. | 27 | resulting in a strange merging of dimensions. |
| 27 | 28 | ||
| 28 | <iframe style="border: 0; width: 100%; height: 42px;" src="https://bandcamp.com/EmbeddedPlayer/album=3913808801/size=small/bgcol=ffffff/linkcol=0687f5/track=1349272965/transparent=true/" seamless title="Bandcamp"><a href="https://mitjafelicijan.bandcamp.com/album/that-sound-that-machine-makes-when-struggling">That sound that machine makes when struggling by Mitja Felicijan</a></iframe> | 29 | <iframe style="border: 0; width: 100%; height: 42px;" src="https://bandcamp.com/EmbeddedPlayer/album=3913808801/size=small/bgcol=ffffff/linkcol=0687f5/track=1349272965/transparent=true/" seamless title="Bandcamp"><a href="https://mitjafelicijan.bandcamp.com/album/that-sound-that-machine-makes-when-struggling">That sound that machine makes when struggling by Mitja Felicijan</a></iframe> |
| 29 | 30 | ||
| 30 | ## Two black holes conversing about the weather | 31 | ## Two black holes conversing about the weather |
| 31 | 32 | ||
| 32 | You are a traveler in a spaceship flying very close to two colliding black holes | 33 | You are a traveler in a spaceship flying very close to two colliding black holes |
| 33 | having a discussion about the weather while tearing each other apart. During | 34 | having a discussion about the weather while tearing each other apart. During all |
| 34 | all this your ship is getting pulled into the event horizon of both black | 35 | this your ship is getting pulled into the event horizon of both black holes, |
| 35 | holes, putting a lot of strain on your spaceship. | 36 | putting a lot of strain on your spaceship. |
| 36 | 37 | ||
| 37 | <iframe style="border: 0; width: 100%; height: 42px;" src="https://bandcamp.com/EmbeddedPlayer/album=3913808801/size=small/bgcol=ffffff/linkcol=0687f5/track=1756714200/transparent=true/" seamless title="Bandcamp"><a href="https://mitjafelicijan.bandcamp.com/album/that-sound-that-machine-makes-when-struggling">That sound that machine makes when struggling by Mitja Felicijan</a></iframe> | 38 | <iframe style="border: 0; width: 100%; height: 42px;" src="https://bandcamp.com/EmbeddedPlayer/album=3913808801/size=small/bgcol=ffffff/linkcol=0687f5/track=1756714200/transparent=true/" seamless title="Bandcamp"><a href="https://mitjafelicijan.bandcamp.com/album/that-sound-that-machine-makes-when-struggling">That sound that machine makes when struggling by Mitja Felicijan</a></iframe> |
| 38 | 39 | ||
| 39 | ## A planet where every organism is a plant | 40 | ## A planet where every organism is a plant |
| 40 | 41 | ||
| 41 | You land on a planet where every living organism is a plant and among those | 42 | You land on a planet where every living organism is a plant and among those |
| 42 | plants some of them are highly intelligent, and you were asked to make first | 43 | plants some of them are highly intelligent, and you were asked to make first |
| 43 | contact with the native species. Your visit takes place in a giant cave where | 44 | contact with the native species. Your visit takes place in a giant cave where |
| 44 | you are meeting these plants, and they are talking to you. | 45 | you are meeting these plants, and they are talking to you. |
| 45 | 46 | ||
| 46 | <iframe style="border: 0; width: 100%; height: 42px;" src="https://bandcamp.com/EmbeddedPlayer/album=3913808801/size=small/bgcol=ffffff/linkcol=0687f5/track=3710973979/transparent=true/" seamless title="Bandcamp"><a href="https://mitjafelicijan.bandcamp.com/album/that-sound-that-machine-makes-when-struggling">That sound that machine makes when struggling by Mitja Felicijan</a></iframe> | 47 | <iframe style="border: 0; width: 100%; height: 42px;" src="https://bandcamp.com/EmbeddedPlayer/album=3913808801/size=small/bgcol=ffffff/linkcol=0687f5/track=3710973979/transparent=true/" seamless title="Bandcamp"><a href="https://mitjafelicijan.bandcamp.com/album/that-sound-that-machine-makes-when-struggling">That sound that machine makes when struggling by Mitja Felicijan</a></iframe> |
| 47 | 48 | ||
| 48 | ## Bio implants having a fit and reprogramming your brain | 49 | ## Bio implants having a fit and reprogramming your brain |
| 49 | 50 | ||
| 50 | In a distant future where everybody has bio implants, you have just received | 51 | In a distant future where everybody has bio implants, you have just received |
| 51 | your first one, which happens to be a brain implant. Something goes wrong, | 52 | your first one, which happens to be a brain implant. Something goes wrong, and |
| 52 | and your implant is starting to misbehave, and you are experiencing brain | 53 | your implant is starting to misbehave, and you are experiencing brain |
| 53 | malfunctions. You are on the streets at night a couple of hours after your | 54 | malfunctions. You are on the streets at night a couple of hours after your |
| 54 | procedure. You can feel your sanity breaking down. | 55 | procedure. You can feel your sanity breaking down. |
| 55 | 56 | ||
| 56 | <iframe style="border: 0; width: 100%; height: 42px;" src="https://bandcamp.com/EmbeddedPlayer/album=3913808801/size=small/bgcol=ffffff/linkcol=0687f5/track=1157430581/transparent=true/" seamless title="Bandcamp"><a href="https://mitjafelicijan.bandcamp.com/album/that-sound-that-machine-makes-when-struggling">That sound that machine makes when struggling by Mitja Felicijan</a></iframe> | 57 | <iframe style="border: 0; width: 100%; height: 42px;" src="https://bandcamp.com/EmbeddedPlayer/album=3913808801/size=small/bgcol=ffffff/linkcol=0687f5/track=1157430581/transparent=true/" seamless title="Bandcamp"><a href="https://mitjafelicijan.bandcamp.com/album/that-sound-that-machine-makes-when-struggling">That sound that machine makes when struggling by Mitja Felicijan</a></iframe> |
| 57 | 58 | ||
| 58 | ## Cow animation | 59 | ## Cow animation |
| 59 | 60 | ||
| 60 | I also made this little cow animation. Go into full screen to see the effects | 61 | I also made this little cow animation. Go into full screen to see the effects in |
| 61 | in more details. | 62 | more details. |
| 62 | 63 | ||
| 63 | <video src="/assets/microsoundtrack/cow.m4v" controls loop></video> | 64 | <video src="/assets/microsoundtrack/cow.m4v" controls loop></video> |
| 64 | 65 | ||
diff --git a/content/posts/2023-01-26-trying-to-build-a-new-kind-of-terminal-emulator.md b/content/posts/2023-01-26-trying-to-build-a-new-kind-of-terminal-emulator.md index 4ec307f..a03a2a4 100644 --- a/content/posts/2023-01-26-trying-to-build-a-new-kind-of-terminal-emulator.md +++ b/content/posts/2023-01-26-trying-to-build-a-new-kind-of-terminal-emulator.md | |||
| @@ -5,32 +5,33 @@ date: 2023-01-26T12:00:00+02:00 | |||
| 5 | draft: false | 5 | draft: false |
| 6 | --- | 6 | --- |
| 7 | 7 | ||
| 8 | Over the past few weeks, I have been really thinking about terminal emulators, | 8 | Over the past few weeks, I have been really thinking about terminal emulators, |
| 9 | how we interact with computers, the separation of text-based programs and GUI | 9 | how we interact with computers, the separation of text-based programs and GUI |
| 10 | ones. To be perfectly honest, I got pissed off one evening when I was cleaning | 10 | ones. To be perfectly honest, I got pissed off one evening when I was cleaning |
| 11 | up files on my computer. Normally, I go into console and do `ncdu` and check | 11 | up files on my computer. Normally, I go into console and do `ncdu` and check |
| 12 | where the junk is. Then I start deleting stuff. Without any discrimination, | 12 | where the junk is. Then I start deleting stuff. Without any discrimination, |
| 13 | usually. But when it comes to screenshots, I have learned that it's good to | 13 | usually. But when it comes to screenshots, I have learned that it's good to keep |
| 14 | keep them somewhere near if I need to refer to something that I was doing. I | 14 | them somewhere near if I need to refer to something that I was doing. I am an |
| 15 | am an avid screenshot taker. So at that point I checked Pictures folder and | 15 | avid screenshot taker. So at that point I checked Pictures folder and also did a |
| 16 | also did a basic search `find . -type f -name "*.jpg"` for all the JPEG files | 16 | basic search `find . -type f -name "*.jpg"` for all the JPEG files in my home |
| 17 | in my home directory and immediately got pissed off. Why can’t I see thumbnails | 17 | directory and immediately got pissed off. Why can’t I see thumbnails in my |
| 18 | in my terminal? I know why, but why in the year of 2022 this is still a | 18 | terminal? I know why, but why in the year of 2022 this is still a problem. I am |
| 19 | problem. I am used to traversing my disk via terminal. I am faster, and I am | 19 | used to traversing my disk via terminal. I am faster, and I am more comfortable |
| 20 | more comfortable this way. But when it comes to visualization, I then need to | 20 | this way. But when it comes to visualization, I then need to revert to GUI |
| 21 | revert to GUI applications and again find the same file to see it. I know that | 21 | applications and again find the same file to see it. I know that programs like |
| 22 | programs like `feh` and `sxiv` are available, but I would just like to see the | 22 | `feh` and `sxiv` are available, but I would just like to see the preview. Like |
| 23 | preview. Like [Jupyter notebook](https://jupyter.org/) or something similar. | 23 | [Jupyter notebook](https://jupyter.org/) or something similar. Just having it |
| 24 | Just having it inline. Part of a result. | 24 | inline. Part of a result. |
| 25 | 25 | ||
| 26 | It also didn’t help that I was spending some time with the [Plan 9](https://plan9.io/plan9/) | 26 | It also didn’t help that I was spending some time with the [Plan |
| 27 | Operating system. More specifically [9FRONT](http://9front.org/). The way | 27 | 9](https://plan9.io/plan9/) Operating system. More specifically |
| 28 | that [ACME editor](http://acme.cat-v.org/) handles text editing is just | 28 | [9FRONT](http://9front.org/). The way that [ACME editor](http://acme.cat-v.org/) |
| 29 | wonderful. Different and fresh somehow, even though it’s super old. | 29 | handles text editing is just wonderful. Different and fresh somehow, even though |
| 30 | 30 | it’s super old. | |
| 31 | So, I went on a lookout for an interesting way of visualizing results of some | 31 | |
| 32 | query. I found these applications to be outstanding examples of how not to be | 32 | So, I went on a lookout for an interesting way of visualizing results of some |
| 33 | a captive of a predetermined way of doing things. | 33 | query. I found these applications to be outstanding examples of how not to be a |
| 34 | captive of a predetermined way of doing things. | ||
| 34 | 35 | ||
| 35 | - [Wolfram Mathematica](https://www.wolfram.com/mathematica/) | 36 | - [Wolfram Mathematica](https://www.wolfram.com/mathematica/) |
| 36 | - [Jupyter notebooks](https://jupyter.org/) | 37 | - [Jupyter notebooks](https://jupyter.org/) |
| @@ -38,56 +39,56 @@ a captive of a predetermined way of doing things. | |||
| 38 | - [Temple OS](https://templeos.org/) | 39 | - [Temple OS](https://templeos.org/) |
| 39 | - [Emacs](https://www.gnu.org/software/emacs/) | 40 | - [Emacs](https://www.gnu.org/software/emacs/) |
| 40 | 41 | ||
| 41 | My idea is not as out there as ACME is, but it is a spin on the terminal | 42 | My idea is not as out there as ACME is, but it is a spin on the terminal |
| 42 | emulators. I like the modes that Vi/Vim provides you with. I like the way | 43 | emulators. I like the modes that Vi/Vim provides you with. I like the way the |
| 43 | the Emacs does its own `M-x` `M-c`. Furthermore, I really like how Mathematica | 44 | Emacs does its own `M-x` `M-c`. Furthermore, I really like how Mathematica and |
| 44 | and Jupyter present the data in a free flowing form. And I love how Temple OS | 45 | Jupyter present the data in a free flowing form. And I love how Temple OS is |
| 45 | is basically a C interpreter on some level. | 46 | basically a C interpreter on some level. |
| 46 | 47 | ||
| 47 | > **Note:** This is part 1 of the journey. Nowhere finished yet. I am just | 48 | > **Note:** This is part 1 of the journey. Nowhere finished yet. I am just |
| 48 | > tinkering with this at the moment. This whole thing can easily spectacularly | 49 | > tinkering with this at the moment. This whole thing can easily spectacularly |
| 49 | > fail. | 50 | > fail. |
| 50 | 51 | ||
| 51 | So I started. I knew that I wanted to have the couple of modes, but I didn’t | 52 | So I started. I knew that I wanted to have the couple of modes, but I didn’t |
| 52 | like the repetition of keystrokes, so the only option was to have some sort of | 53 | like the repetition of keystrokes, so the only option was to have some sort of |
| 53 | toggle and indicate to the user that they are in a special mode. Like Vi does | 54 | toggle and indicate to the user that they are in a special mode. Like Vi does |
| 54 | for Normal and Visual mode. | 55 | for Normal and Visual mode. |
| 55 | 56 | ||
| 56 | These modes would for the first version be: | 57 | These modes would for the first version be: |
| 57 | 58 | ||
| 58 | - *Preview mode* (toggle with Ctrl + P) | 59 | - *Preview mode* (toggle with Ctrl + P) |
| 59 | - When this mode would be enabled, the `ls` command would try to find images | 60 | - When this mode would be enabled, the `ls` command would try to find images |
| 60 | from the results and display thumbnails from them in the terminal itself. | 61 | from the results and display thumbnails from them in the terminal itself. |
| 61 | No ASCII art. Proper images. In a grid! | 62 | No ASCII art. Proper images. In a grid! |
| 62 | - *Detach mode* (toggle with Ctrl + D) | 63 | - *Detach mode* (toggle with Ctrl + D) |
| 63 | - When this mode would be enabled, every command would open a new window | 64 | - When this mode would be enabled, every command would open a new window |
| 64 | and execute that command in it. This would be useful for starting `htop` | 65 | and execute that command in it. This would be useful for starting `htop` |
| 65 | in a separate window. | 66 | in a separate window. |
| 66 | 67 | ||
| 67 | The reason for having these modes togglable is to not ask for previews every | 68 | The reason for having these modes togglable is to not ask for previews every |
| 68 | time. You enable a mode and until you disable it, it behaves that way. | 69 | time. You enable a mode and until you disable it, it behaves that way. Purely |
| 69 | Purely out of ergonomic reasons. | 70 | out of ergonomic reasons. |
| 70 | 71 | ||
| 71 | I would like to treat every terminal I open as a session mentally. When I start | 72 | I would like to treat every terminal I open as a session mentally. When I start |
| 72 | using the terminal, I start digging deeper into the issue I am trying to resolve. | 73 | using the terminal, I start digging deeper into the issue I am trying to |
| 73 | And while I am doing this, I would like to open detached windows etc. A lot of | 74 | resolve. And while I am doing this, I would like to open detached windows |
| 74 | these things can be done easily with something like [i3](https://i3wm.org/), | 75 | etc. A lot of these things can be done easily with something like |
| 75 | but also that pull you out of the context of what you were doing. I would | 76 | [i3](https://i3wm.org/), but also that pull you out of the context of what you |
| 76 | like to orchestrate everything from one single point. | 77 | were doing. I would like to orchestrate everything from one single point. |
| 77 | 78 | ||
| 78 | In planning for this project, I knew that I would need to use a language like | 79 | In planning for this project, I knew that I would need to use a language like C |
| 79 | C and a library such as [SDL2](https://www.libsdl.org/) in order to achieve | 80 | and a library such as [SDL2](https://www.libsdl.org/) in order to achieve the |
| 80 | the desired results. I had considered other options, but ultimately determined | 81 | desired results. I had considered other options, but ultimately determined that |
| 81 | that [SDL2](https://www.libsdl.org/) was the best fit based on its capabilities | 82 | [SDL2](https://www.libsdl.org/) was the best fit based on its capabilities and |
| 82 | and reputation in the programming community. | 83 | reputation in the programming community. |
| 83 | 84 | ||
| 84 | At first, I thought the idea of a hardware accelerated terminal was a bit of | 85 | At first, I thought the idea of a hardware accelerated terminal was a bit of a |
| 85 | a joke. It seemed like such a niche and unnecessary feature, especially given | 86 | joke. It seemed like such a niche and unnecessary feature, especially given the |
| 86 | the fact that terminal emulators have been around for decades and have always | 87 | fact that terminal emulators have been around for decades and have always relied |
| 87 | relied on software rendering. But to be fair, [Alacritty](https://alacritty.org/) | 88 | on software rendering. But to be fair, [Alacritty](https://alacritty.org/) is |
| 88 | is doing the same thing. Well, they are doing a remarkable job at it. | 89 | doing the same thing. Well, they are doing a remarkable job at it. |
| 89 | 90 | ||
| 90 | So, I embarked on a journey. Everything has to start somewhere. For me, it | 91 | So, I embarked on a journey. Everything has to start somewhere. For me, it |
| 91 | started with creating a window! It has to start somewhere. 🙂 | 92 | started with creating a window! It has to start somewhere. 🙂 |
| 92 | 93 | ||
| 93 | ```c | 94 | ```c |
| @@ -101,28 +102,31 @@ SDL_Window *window = SDL_CreateWindow( | |||
| 101 | 102 | ||
| 102 | I continued like this to get some text displayed on the screen. | 103 | I continued like this to get some text displayed on the screen. |
| 103 | 104 | ||
| 104 | I noted that [`TTF_RenderText_Solid`](https://wiki.libsdl.org/SDL_ttf/TTF_RenderText_Solid) | 105 | I noted that |
| 105 | rendered text really poorly. There were no antialiasing at all. In my wisdom, | 106 | [`TTF_RenderText_Solid`](https://wiki.libsdl.org/SDL_ttf/TTF_RenderText_Solid) |
| 106 | I never checked the documentation. Well, that was a fail. To uneducated like | 107 | rendered text really poorly. There were no antialiasing at all. In my wisdom, I |
| 107 | me: `TTF_RenderText_Solid` renders Latin1 text at fast quality to a new 8-bit | 108 | never checked the documentation. Well, that was a fail. To uneducated like me: |
| 109 | `TTF_RenderText_Solid` renders Latin1 text at fast quality to a new 8-bit | ||
| 108 | surface. So, that's why the texts looked like shit. No wonder. | 110 | surface. So, that's why the texts looked like shit. No wonder. |
| 109 | 111 | ||
| 110 | Remarks on `TTF_RenderText_Solid`: This function will allocate a new 8-bit, | 112 | Remarks on `TTF_RenderText_Solid`: This function will allocate a new 8-bit, |
| 111 | palettized surface. The surface's 0 pixel will be the colorkey, giving a | 113 | palettized surface. The surface's 0 pixel will be the colorkey, giving a |
| 112 | transparent background. The 1 pixel will be set to the text color. | 114 | transparent background. The 1 pixel will be set to the text color. |
| 113 | 115 | ||
| 114 | After I replaced it with [`TTF_RenderText_LCD`](https://wiki.libsdl.org/SDL_ttf/TTF_RenderText_LCD) | 116 | After I replaced it with |
| 115 | which renders Latin1 text at LCD subpixel quality to a new ARGB surface, the | 117 | [`TTF_RenderText_LCD`](https://wiki.libsdl.org/SDL_ttf/TTF_RenderText_LCD) which |
| 116 | text started looking good. Really make sure you read the documentation. It’s | 118 | renders Latin1 text at LCD subpixel quality to a new ARGB surface, the text |
| 117 | actually good. As a side note, you can find all the documentation regarding | 119 | started looking good. Really make sure you read the documentation. It’s actually |
| 118 | [SDL2 on their Wiki](https://wiki.libsdl.org/). | 120 | good. As a side note, you can find all the documentation regarding [SDL2 on |
| 119 | 121 | their Wiki](https://wiki.libsdl.org/). | |
| 120 | After that was done, I started working on displaying other things like | 122 | |
| 121 | `Preview` and `Detach` modes. This wasn’t really that hard. In SDL2 you can | 123 | After that was done, I started working on displaying other things like `Preview` |
| 122 | check all the available events with `while (SDL_PollEvent(&event) > 0)` and | 124 | and `Detach` modes. This wasn’t really that hard. In SDL2 you can check all the |
| 123 | have a bunch of switch statements to determine which key is currently being | 125 | available events with `while (SDL_PollEvent(&event) > 0)` and have a bunch of |
| 124 | pressed. More about keys, [SDLKey](https://documentation.help/SDL/sdlkey.html) | 126 | switch statements to determine which key is currently being pressed. More about |
| 125 | and mroe about pooling the events on [SDL_PollEvent](https://documentation.help/SDL/sdlpollevent.html). | 127 | keys, [SDLKey](https://documentation.help/SDL/sdlkey.html) and mroe about |
| 128 | pooling the events on | ||
| 129 | [SDL_PollEvent](https://documentation.help/SDL/sdlpollevent.html). | ||
| 126 | 130 | ||
| 127 | ```c | 131 | ```c |
| 128 | while (SDL_PollEvent(&event) > 0) | 132 | while (SDL_PollEvent(&event) > 0) |
| @@ -144,9 +148,9 @@ while (SDL_PollEvent(&event) > 0) | |||
| 144 | } | 148 | } |
| 145 | ``` | 149 | ``` |
| 146 | 150 | ||
| 147 | After that was somewhat working correctly, I started creating a struct that | 151 | After that was somewhat working correctly, I started creating a struct that |
| 148 | would hold all the commands and results and I call them Cells. Yes, I stole | 152 | would hold all the commands and results and I call them Cells. Yes, I stole that |
| 149 | that naming idea from Jupyter. | 153 | naming idea from Jupyter. |
| 150 | 154 | ||
| 151 | ```c | 155 | ```c |
| 152 | typedef struct | 156 | typedef struct |
| @@ -159,13 +163,15 @@ typedef struct | |||
| 159 | } Cell; | 163 | } Cell; |
| 160 | ``` | 164 | ``` |
| 161 | 165 | ||
| 162 | I am at a place now where I am starting to implement scrolling. This will for | 166 | I am at a place now where I am starting to implement scrolling. This will for |
| 163 | sure be fun to code. Memory management in C is super easy. 😂 | 167 | sure be fun to code. Memory management in C is super easy. 😂 |
| 164 | 168 | ||
| 165 | I have also added a simple [INI file like configuration](https://en.wikipedia.org/wiki/INI_file) | 169 | I have also added a simple [INI file like |
| 166 | support. It is done in an [STB style of header](https://github.com/nothings/stb/blob/master/docs/stb_howto.txt) | 170 | configuration](https://en.wikipedia.org/wiki/INI_file) support. It is done in an |
| 167 | and maps to specific options supported by the terminal. It is not universal, | 171 | [STB style of |
| 168 | and the code below demonstrates how I will use it in the future. | 172 | header](https://github.com/nothings/stb/blob/master/docs/stb_howto.txt) and maps |
| 173 | to specific options supported by the terminal. It is not universal, and the code | ||
| 174 | below demonstrates how I will use it in the future. | ||
| 169 | 175 | ||
| 170 | ```c | 176 | ```c |
| 171 | #ifndef CONFIG_H | 177 | #ifndef CONFIG_H |
| @@ -239,8 +245,8 @@ extern Config read_config_file(const char *filename) | |||
| 239 | #endif | 245 | #endif |
| 240 | ``` | 246 | ``` |
| 241 | 247 | ||
| 242 | This is as far as I managed to get for now. I have a daily job and this | 248 | This is as far as I managed to get for now. I have a daily job and this |
| 243 | prohibits me to work on these things full time. But I should probably get | 249 | prohibits me to work on these things full time. But I should probably get back |
| 244 | back and finish this. At least have a simple version working out, so I can | 250 | and finish this. At least have a simple version working out, so I can start |
| 245 | start testing it on my machines. Fingers crossed. 🕵️♂️ | 251 | testing it on my machines. Fingers crossed. 🕵️♂️ |
| 246 | 252 | ||
diff --git a/content/posts/2023-05-10-push-to-multiple-origins-at-once-in-git.md b/content/posts/2023-05-10-push-to-multiple-origins-at-once-in-git.md index 3d07072..adef7e9 100644 --- a/content/posts/2023-05-10-push-to-multiple-origins-at-once-in-git.md +++ b/content/posts/2023-05-10-push-to-multiple-origins-at-once-in-git.md | |||
| @@ -5,21 +5,20 @@ date: 2023-05-10T12:00:00+02:00 | |||
| 5 | draft: false | 5 | draft: false |
| 6 | --- | 6 | --- |
| 7 | 7 | ||
| 8 | This is a quick one. I use my personal Git server as my main server, and I use | 8 | This is a quick one. I use my personal Git server as my main server, and I use |
| 9 | GitHub only as a mirror. As a result, I constantly forget to push to GitHub. | 9 | GitHub only as a mirror. As a result, I constantly forget to push to GitHub. |
| 10 | 10 | ||
| 11 | To push to multiple origins at once in Git, you can create a custom Git alias | 11 | To push to multiple origins at once in Git, you can create a custom Git alias or |
| 12 | or use a script to automate the process. Here's an example of how you can | 12 | use a script to automate the process. Here's an example of how you can achieve |
| 13 | achieve this using a Git alias: | 13 | this using a Git alias: |
| 14 | 14 | ||
| 15 | ```sh | 15 | ```sh |
| 16 | git config --global alias.pushall '!sh -c "git remote | xargs -L1 git push --all"' | 16 | git config --global alias.pushall '!sh -c "git remote | xargs -L1 git push --all"' |
| 17 | ``` | 17 | ``` |
| 18 | 18 | ||
| 19 | This command creates a Git alias called `pushall` which, when executed, will | 19 | This command creates a Git alias called `pushall` which, when executed, will |
| 20 | push the changes to all the remote repositories associated with the current | 20 | push the changes to all the remote repositories associated with the current |
| 21 | repository. To use it, simply run `git pushall` instead of `git push` when | 21 | repository. To use it, simply run `git pushall` instead of `git push` when you |
| 22 | you want to push to all the remote repositories at once. | 22 | want to push to all the remote repositories at once. |
| 23 | 23 | ||
| 24 | That's all, folks. | 24 | That's all, folks. |
| 25 | |||
diff --git a/content/posts/2023-05-16-rekindling-my-love-for-programming.md b/content/posts/2023-05-16-rekindling-my-love-for-programming.md index 6b73bb1..fb8add2 100644 --- a/content/posts/2023-05-16-rekindling-my-love-for-programming.md +++ b/content/posts/2023-05-16-rekindling-my-love-for-programming.md | |||
| @@ -5,72 +5,69 @@ date: 2023-05-16T12:00:00+02:00 | |||
| 5 | draft: false | 5 | draft: false |
| 6 | --- | 6 | --- |
| 7 | 7 | ||
| 8 | Programming can be a challenging and rewarding experience, but sometimes it's | 8 | Programming can be a challenging and rewarding experience, but sometimes it's |
| 9 | easy to feel burnt out or disinterested. I have lost the passion for coding | 9 | easy to feel burnt out or disinterested. I have lost the passion for coding over |
| 10 | over the past couple of months and it looked like I will never enjoy the | 10 | the past couple of months and it looked like I will never enjoy the coding as |
| 11 | coding as much as I did. | 11 | much as I did. |
| 12 | 12 | ||
| 13 | I was feeling burnt out with programming. I thought taking a break from it | 13 | I was feeling burnt out with programming. I thought taking a break from it and |
| 14 | and focusing on other activities that I enjoy might be helpful. This way, I | 14 | focusing on other activities that I enjoy might be helpful. This way, I could |
| 15 | could come back to programming with a fresh perspective and renewed energy. | 15 | come back to programming with a fresh perspective and renewed energy. I also |
| 16 | I also thought about learning a new programming language or technology to | 16 | thought about learning a new programming language or technology to keep things |
| 17 | keep things interesting and challenging. | 17 | interesting and challenging. |
| 18 | 18 | ||
| 19 | However, what I didn't realize was that learning a new language or technology | 19 | However, what I didn't realize was that learning a new language or technology |
| 20 | wasn't going to solve the underlying issue. I needed to take a step back and | 20 | wasn't going to solve the underlying issue. I needed to take a step back and |
| 21 | re-evaluate why I had lost my passion for programming in the first place. | 21 | re-evaluate why I had lost my passion for programming in the first place. This |
| 22 | This involved taking a deep look into what I was doing that resulted in | 22 | involved taking a deep look into what I was doing that resulted in this rut. |
| 23 | this rut. | ||
| 24 | 23 | ||
| 25 | Sometimes, it's easy to get caught up in the hype of new technologies or | 24 | Sometimes, it's easy to get caught up in the hype of new technologies or |
| 26 | languages, and we can feel like we're missing out if we're not constantly | 25 | languages, and we can feel like we're missing out if we're not constantly |
| 27 | learning and experimenting. However, it's important to remember that the | 26 | learning and experimenting. However, it's important to remember that the latest |
| 28 | latest and greatest isn't always the best fit for our projects or our | 27 | and greatest isn't always the best fit for our projects or our |
| 29 | interests. Instead of constantly chasing the next big thing, it can be helpful | 28 | interests. Instead of constantly chasing the next big thing, it can be helpful |
| 30 | to focus on what truly interests us and what we're passionate about. This | 29 | to focus on what truly interests us and what we're passionate about. This can |
| 31 | can help us stay motivated and engaged with our work, rather than feeling | 30 | help us stay motivated and engaged with our work, rather than feeling like we're |
| 32 | like we're just going through the motions. | 31 | just going through the motions. |
| 33 | 32 | ||
| 34 | I expressed that I had lost my passion for coding over the past couple of | 33 | I expressed that I had lost my passion for coding over the past couple of |
| 35 | months, and I realized that the reason behind it was my tendency to spread | 34 | months, and I realized that the reason behind it was my tendency to spread |
| 36 | myself too thin and not focus on completing interesting projects. In order | 35 | myself too thin and not focus on completing interesting projects. In order to |
| 37 | to regain my passion for coding, I need to focus on projects that truly | 36 | regain my passion for coding, I need to focus on projects that truly interest me |
| 38 | interest me and give me a sense of purpose and motivation. | 37 | and give me a sense of purpose and motivation. |
| 39 | 38 | ||
| 40 | Recently, I have been playing World of Warcraft more frequently and have | 39 | Recently, I have been playing World of Warcraft more frequently and have become |
| 41 | become interested in developing addons for the game. | 40 | interested in developing addons for the game. |
| 42 | 41 | ||
| 43 | This quickly resulted in me creating three addons that improve the quality | 42 | This quickly resulted in me creating three addons that improve the quality of |
| 44 | of life, and I subsequently developed a more useful add-on that encapsulates | 43 | life, and I subsequently developed a more useful add-on that encapsulates all |
| 45 | all the others I made. | 44 | the others I made. |
| 46 | 45 | ||
| 47 | I found it interesting that this action sparked a new interest in me. | 46 | I found it interesting that this action sparked a new interest in me. |
| 48 | Additionally, I discovered the Lua language, which reminded me that coding | 47 | Additionally, I discovered the Lua language, which reminded me that coding |
| 49 | should be fun rather than just a struggle with a language. It should be | 48 | should be fun rather than just a struggle with a language. It should be pure, |
| 50 | pure, unadulterated fun. | 49 | unadulterated fun. |
| 51 | 50 | ||
| 52 | I wasn't fighting the syntax, nor was I focused on finding the most optimal | 51 | I wasn't fighting the syntax, nor was I focused on finding the most optimal |
| 53 | solution. I simply created things without the pressure of making them the | 52 | solution. I simply created things without the pressure of making them the best |
| 54 | best they could possibly be. | 53 | they could possibly be. |
| 55 | 54 | ||
| 56 | This made me realize that I actually adore simple languages that get out of | 55 | This made me realize that I actually adore simple languages that get out of the |
| 57 | the way and let you express what you want to do. It forced me to rethink a | 56 | way and let you express what you want to do. It forced me to rethink a lot about |
| 58 | lot about what I use and what I actually enjoy. | 57 | what I use and what I actually enjoy. |
| 59 | 58 | ||
| 60 | I have decided to stick to the basics. For a scripting language, I will use | 59 | I have decided to stick to the basics. For a scripting language, I will use |
| 61 | Lua. For networking, I will use Golang. And for any special needs, I will | 60 | Lua. For networking, I will use Golang. And for any special needs, I will rely |
| 62 | rely on C. I do not require Rust, Nim, or Zig. This selection is more than | 61 | on C. I do not require Rust, Nim, or Zig. This selection is more than sufficient |
| 63 | sufficient for my needs. I have to stay true to this simplicity. There is | 62 | for my needs. I have to stay true to this simplicity. There is something to the |
| 64 | something to the Occam's Razor. | 63 | Occam's Razor. |
| 65 | 64 | ||
| 66 | I've been struggling with a lack of creativity lately, but now I'm experiencing | 65 | I've been struggling with a lack of creativity lately, but now I'm experiencing |
| 67 | a real change. I realized I needed to take a step back and stop actively trying | 66 | a real change. I realized I needed to take a step back and stop actively trying |
| 68 | to address the issue. I needed to stop worrying and overthinking it. I simply | 67 | to address the issue. I needed to stop worrying and overthinking it. I simply |
| 69 | needed some time. Looking back, I don't think I've taken any significant time | 68 | needed some time. Looking back, I don't think I've taken any significant time |
| 70 | off in the last 10 years. | 69 | off in the last 10 years. |
| 71 | 70 | ||
| 72 | Suddenly, I find myself with the energy and passion to complete multiple | 71 | Suddenly, I find myself with the energy and passion to complete multiple small |
| 73 | small projects. It doesn't feel like a chore at all. Who knew I needed WoW | 72 | projects. It doesn't feel like a chore at all. Who knew I needed WoW to |
| 74 | to kickstart everything. Inspiration really does come from the strangest | 73 | kickstart everything. Inspiration really does come from the strangest places. |
| 75 | places. | ||
| 76 | |||
diff --git a/content/posts/2023-05-22-crafting-stories-in-zed-editor.md b/content/posts/2023-05-22-crafting-stories-in-zed-editor.md index f5240da..ead4276 100644 --- a/content/posts/2023-05-22-crafting-stories-in-zed-editor.md +++ b/content/posts/2023-05-22-crafting-stories-in-zed-editor.md | |||
| @@ -5,37 +5,38 @@ date: 2023-05-22T12:00:00+02:00 | |||
| 5 | draft: false | 5 | draft: false |
| 6 | --- | 6 | --- |
| 7 | 7 | ||
| 8 | Pretentious title! Good start! I have nothing to add to this discussion. I just | 8 | Pretentious title! Good start! I have nothing to add to this discussion. I just |
| 9 | like this editor and wanted to write something here that will remind me to | 9 | like this editor and wanted to write something here that will remind me to use |
| 10 | use it again in a while when/if it becomes available for Linux. | 10 | it again in a while when/if it becomes available for Linux. |
| 11 | 11 | ||
| 12 | **TLDR:** I think this code editor is very cool and has a massive potential. | 12 | **TLDR:** I think this code editor is very cool and has a massive potential. I |
| 13 | I hope they don’t mess up with adding a plugin ecosystem to it! | 13 | hope they don’t mess up with adding a plugin ecosystem to it! |
| 14 | 14 | ||
| 15 | Out of morbid curiosity, I started using the [Zed editor](https://zed.dev/) | 15 | Out of morbid curiosity, I started using the [Zed editor](https://zed.dev/) on |
| 16 | on my Mac. Zed is a high-performance, multiplayer code editor developed by | 16 | my Mac. Zed is a high-performance, multiplayer code editor developed by the |
| 17 | the creators of Atom and Tree-sitter. Written in Rust so it has to be | 17 | creators of Atom and Tree-sitter. Written in Rust so it has to be blazingly |
| 18 | blazingly fast! 😊 It's a joke, calm down. | 18 | fast! 😊 It's a joke, calm down. |
| 19 | 19 | ||
| 20 | Over the past year, I have switched between [Helix editor](https://helix-editor.com/) | 20 | Over the past year, I have switched between [Helix |
| 21 | and [VS Code](https://code.visualstudio.com/), but for the last couple of | 21 | editor](https://helix-editor.com/) and [VS |
| 22 | months, I have been using Helix exclusively. | 22 | Code](https://code.visualstudio.com/), but for the last couple of months, I have |
| 23 | been using Helix exclusively. | ||
| 23 | 24 | ||
| 24 | I've been genuinely impressed by Zed. When you open a file, it automatically | 25 | I've been genuinely impressed by Zed. When you open a file, it automatically |
| 25 | detects its type and downloads the corresponding [LSP (language server)](https://en.wikipedia.org/wiki/Language_Server_Protocol). | 26 | detects its type and downloads the corresponding [LSP (language |
| 26 | The list of supported languages is not extensive, but it's still impressive. | 27 | server)](https://en.wikipedia.org/wiki/Language_Server_Protocol). The list of |
| 27 | It's a great example of how to create a product that stays out of your way. | 28 | supported languages is not extensive, but it's still impressive. It's a great |
| 29 | example of how to create a product that stays out of your way. | ||
| 28 | 30 | ||
| 29 |  | 31 |  |
| 30 | 32 | ||
| 31 | For C development it downloaded [clangd](https://clangd.llvm.org/) and setting | 33 | For C development it downloaded [clangd](https://clangd.llvm.org/) and setting |
| 32 | up missing dependencies in code was rather easy. For this project I use | 34 | up missing dependencies in code was rather easy. For this project I use |
| 33 | [SDL2](https://www.libsdl.org/) for rendering terminal emulator. It’s a | 35 | [SDL2](https://www.libsdl.org/) for rendering terminal emulator. It’s a hobby |
| 34 | hobby project, don’t worry about it. | 36 | project, don’t worry about it. |
| 35 | 37 | ||
| 36 | If you are going to give this a try and you are using C, I suggest checking | 38 | If you are going to give this a try and you are using C, I suggest checking two |
| 37 | two files in the root of your project folder. If you don't have them, | 39 | files in the root of your project folder. If you don't have them, create them. |
| 38 | create them. | ||
| 39 | 40 | ||
| 40 | **compile_flags.txt** | 41 | **compile_flags.txt** |
| 41 | 42 | ||
| @@ -44,10 +45,9 @@ create them. | |||
| 44 | -I/opt/homebrew/include/SDL2 | 45 | -I/opt/homebrew/include/SDL2 |
| 45 | ``` | 46 | ``` |
| 46 | 47 | ||
| 47 | Easy way of checking what the appropriate includes for a specific library is | 48 | Easy way of checking what the appropriate includes for a specific library is to |
| 48 | to use `pkg-config` and in my case `pkg-config SDL2 --cflags-only-I`. But this | 49 | use `pkg-config` and in my case `pkg-config SDL2 --cflags-only-I`. But this is |
| 49 | is nothing new to C/C++ devs. Just a noter for people who are using Visual | 50 | nothing new to C/C++ devs. Just a noter for people who are using Visual Studio. |
| 50 | Studio. | ||
| 51 | 51 | ||
| 52 | **.clang-format** | 52 | **.clang-format** |
| 53 | 53 | ||
| @@ -58,31 +58,30 @@ BasedOnStyle: Mozilla | |||
| 58 | 58 | ||
| 59 | I prefer Mozilla coding style for C so you can set that up. | 59 | I prefer Mozilla coding style for C so you can set that up. |
| 60 | 60 | ||
| 61 | They really have something special here. Although there is no version available | 61 | They really have something special here. Although there is no version available |
| 62 | for Linux yet, I will stick to Helix. This impressive piece of engineering is, | 62 | for Linux yet, I will stick to Helix. This impressive piece of engineering is, |
| 63 | above all, an amazing example of craftsmanship. | 63 | above all, an amazing example of craftsmanship. |
| 64 | 64 | ||
| 65 | They have a bunch of amazing integrated functionalities like live desktop | 65 | They have a bunch of amazing integrated functionalities like live desktop |
| 66 | sharing, code sharing in a live coding session. There is a lot of pretentious | 66 | sharing, code sharing in a live coding session. There is a lot of pretentious |
| 67 | marketing speak there but the product is still amazing! | 67 | marketing speak there but the product is still amazing! |
| 68 | 68 | ||
| 69 | For me the speed and the simplicity of the product was the most impressive | 69 | For me the speed and the simplicity of the product was the most impressive |
| 70 | thing. You get that: it just works feeling. A rare thing in 2023. | 70 | thing. You get that: it just works feeling. A rare thing in 2023. |
| 71 | 71 | ||
| 72 |  | 72 |  |
| 73 | 73 | ||
| 74 | They also managed to add [Github Copilot](https://github.com/features/copilot) | 74 | They also managed to add [Github Copilot](https://github.com/features/copilot) |
| 75 | in a non obtrusive way. To me, everything feels very intentional and | 75 | in a non obtrusive way. To me, everything feels very intentional and |
| 76 | specifically selected. It's minimal yet maximally effective. | 76 | specifically selected. It's minimal yet maximally effective. |
| 77 | 77 | ||
| 78 | <video src="https://zed.dev/img/post/copilot/copilot-demo.webm" autoplay loop></video> | 78 | <video src="https://zed.dev/img/post/copilot/copilot-demo.webm" autoplay loop></video> |
| 79 | 79 | ||
| 80 | It is a perfect balance between VS Code, Jetbrains IDE’s and something like | 80 | It is a perfect balance between VS Code, Jetbrains IDE’s and something like VIM |
| 81 | VIM or Helix. | 81 | or Helix. |
| 82 | 82 | ||
| 83 | I just hope they **DON’T** add plugin support and keep it like it is. They as a | 83 | I just hope they **DON’T** add plugin support and keep it like it is. They as a |
| 84 | vendor should add stuff to it with great deliberation and thought. And this | 84 | vendor should add stuff to it with great deliberation and thought. And this way |
| 85 | way the product will stay fast and focused. That’s my two cents. | 85 | the product will stay fast and focused. That’s my two cents. |
| 86 | 86 | ||
| 87 | Amazing job! | 87 | Amazing job! |
| 88 | |||
diff --git a/content/posts/2023-05-23-i-was-wrong-about-git-workflows.md b/content/posts/2023-05-23-i-was-wrong-about-git-workflows.md index e1e45e8..16739de 100644 --- a/content/posts/2023-05-23-i-was-wrong-about-git-workflows.md +++ b/content/posts/2023-05-23-i-was-wrong-about-git-workflows.md | |||
| @@ -7,66 +7,65 @@ type: posts | |||
| 7 | tags: [] | 7 | tags: [] |
| 8 | --- | 8 | --- |
| 9 | 9 | ||
| 10 | I have been using some approximation of [Git Flow](https://jeffkreeftmeijer.com/git-flow/) | 10 | I have been using some approximation of [Git |
| 11 | for years now and never really questioned it to be honest. When I create a repo | 11 | Flow](https://jeffkreeftmeijer.com/git-flow/) for years now and never really |
| 12 | I create develop branch and set it as default one and then merge to master | 12 | questioned it to be honest. When I create a repo I create develop branch and set |
| 13 | from there. Seems reasonable enough. | 13 | it as default one and then merge to master from there. Seems reasonable enough. |
| 14 | 14 | ||
| 15 | One thing that I have learned is that long living branches are the devil. | 15 | One thing that I have learned is that long living branches are the devil. They |
| 16 | They always end up making a huge mess when they need to be merged eventually | 16 | always end up making a huge mess when they need to be merged eventually into |
| 17 | into master. So by that reason, what is the develop branch if not the longest | 17 | master. So by that reason, what is the develop branch if not the longest living |
| 18 | living feature branch. And from my personal experience there was never a | 18 | feature branch. And from my personal experience there was never a situation |
| 19 | situation where I wasn’t sweating bullets when I had to merge develop back | 19 | where I wasn’t sweating bullets when I had to merge develop back to master. |
| 20 | to master. | ||
| 21 | 20 | ||
| 22 | This realisation started to give me pause. So why the hell am I doing this, | 21 | This realisation started to give me pause. So why the hell am I doing this, and |
| 23 | and is there a better way. Well the solution was always there. And it comes | 22 | is there a better way. Well the solution was always there. And it comes in a |
| 24 | in a form of [git tags](https://git-scm.com/book/en/v2/Git-Basics-Tagging). | 23 | form of [git tags](https://git-scm.com/book/en/v2/Git-Basics-Tagging). |
| 25 | 24 | ||
| 26 | So what are git tags? Git tags are references to specific points in a Git | 25 | So what are git tags? Git tags are references to specific points in a Git |
| 27 | repository's history. They are used to mark important milestones, such as | 26 | repository's history. They are used to mark important milestones, such as |
| 28 | releases or significant commits, making it easier to identify and access | 27 | releases or significant commits, making it easier to identify and access |
| 29 | specific versions of a project. | 28 | specific versions of a project. |
| 30 | 29 | ||
| 31 | Somehow we have all hijacked the meaning of the master branch that it has | 30 | Somehow we have all hijacked the meaning of the master branch that it has to be |
| 32 | to be the most releasable version of code. And this is also where the confusing | 31 | the most releasable version of code. And this is also where the confusing about |
| 33 | about versioning the software kicks in. Because master branch implicitly says | 32 | versioning the software kicks in. Because master branch implicitly says that we |
| 34 | that we are dealing with the rolling release type of a software. And by having | 33 | are dealing with the rolling release type of a software. And by having a develop |
| 35 | a develop branch we are hacking around this confusion. With a separation of | 34 | branch we are hacking around this confusion. With a separation of develop and |
| 36 | develop and master we lock functionalities into place and forcing a stable | 35 | master we lock functionalities into place and forcing a stable vs development |
| 37 | vs development version of the software. | 36 | version of the software. |
| 38 | 37 | ||
| 39 | But if that is true and the long living branches are the devil then why have | 38 | But if that is true and the long living branches are the devil then why have |
| 40 | develop at all. I think that most of this comes to how continuous integration | 39 | develop at all. I think that most of this comes to how continuous integration is |
| 41 | is being done. There usually is no granular access to tags and CD software | 40 | being done. There usually is no granular access to tags and CD software deploys |
| 42 | deploys what is present on a specific branch, may that be master for production | 41 | what is present on a specific branch, may that be master for production and |
| 43 | and develop for staging. This is a gross simplification and by having this | 42 | develop for staging. This is a gross simplification and by having this in place |
| 44 | in place we have completely removed tagging as a viable option to create a | 43 | we have completely removed tagging as a viable option to create a fix point in |
| 45 | fix point in software cycle that says, this is the production ready code. | 44 | software cycle that says, this is the production ready code. |
| 46 | 45 | ||
| 47 | One cool thing about tags are that you can checkout a specific tag. So they | 46 | One cool thing about tags are that you can checkout a specific tag. So they |
| 48 | behave very similarly as branches in that regard. And you don’t have the | 47 | behave very similarly as branches in that regard. And you don’t have the |
| 49 | overhead of having two mainstream branches. | 48 | overhead of having two mainstream branches. |
| 50 | 49 | ||
| 51 | So what is the solution? One approach is to use development workflow, where | 50 | So what is the solution? One approach is to use development workflow, where all |
| 52 | all changes are made on the smaller branches and continuously merged into | 51 | changes are made on the smaller branches and continuously merged into |
| 53 | master. Where the software is ready to be pushed to production you tag the | 52 | master. Where the software is ready to be pushed to production you tag the |
| 54 | master branch. This approach eliminates the need for long-lived branches and | 53 | master branch. This approach eliminates the need for long-lived branches and |
| 55 | simplifies the development process. It also encourages developers to make | 54 | simplifies the development process. It also encourages developers to make small, |
| 56 | small, incremental changes that can be tested and deployed quickly. However, | 55 | incremental changes that can be tested and deployed quickly. However, this |
| 57 | this approach may not be suitable for all projects or teams that heavily rely | 56 | approach may not be suitable for all projects or teams that heavily rely on |
| 58 | on automated deployment based on branch names only. | 57 | automated deployment based on branch names only. |
| 59 | 58 | ||
| 60 | This also requires that developers always keep production in mind. No more | 59 | This also requires that developers always keep production in mind. No more |
| 61 | living on an island of the develop branch. All your actions and code need to | 60 | living on an island of the develop branch. All your actions and code need to be |
| 62 | be ready to meet production standards on a much smaller timescale. | 61 | ready to meet production standards on a much smaller timescale. |
| 63 | 62 | ||
| 64 | I think that we have complicated the workflow in an honest attempt to make | 63 | I think that we have complicated the workflow in an honest attempt to make |
| 65 | things more streamlined but in the process of doing this, we have inadvertently | 64 | things more streamlined but in the process of doing this, we have inadvertently |
| 66 | made our lives much more complicated. | 65 | made our lives much more complicated. |
| 67 | 66 | ||
| 68 | In conclusion, it's important to re-evaluate our workflows from time to time | 67 | In conclusion, it's important to re-evaluate our workflows from time to time to |
| 69 | to see if they still make sense and if there are better alternatives available. | 68 | see if they still make sense and if there are better alternatives available. |
| 70 | Long-living branches can be problematic, and using tags to mark important | 69 | Long-living branches can be problematic, and using tags to mark important |
| 71 | milestones can simplify the development process. | 70 | milestones can simplify the development process. |
| 72 | 71 | ||
diff --git a/content/posts/2023-05-31-re-inventing-task-runner-that-i-actually-used-daily.md b/content/posts/2023-05-31-re-inventing-task-runner-that-i-actually-used-daily.md index 17fdaf6..1abfd1e 100644 --- a/content/posts/2023-05-31-re-inventing-task-runner-that-i-actually-used-daily.md +++ b/content/posts/2023-05-31-re-inventing-task-runner-that-i-actually-used-daily.md | |||
| @@ -5,55 +5,49 @@ date: 2023-05-31T12:21:10+02:00 | |||
| 5 | draft: false | 5 | draft: false |
| 6 | --- | 6 | --- |
| 7 | 7 | ||
| 8 | Couple of months ago I had this brilliant idea of re-inventing the wheel | 8 | Couple of months ago I had this brilliant idea of re-inventing the wheel by |
| 9 | by making an alternative for make. And so I went. Boldly into the | 9 | making an alternative for make. And so I went. Boldly into the battle. And to my |
| 10 | battle. And to my big surprise my attempt resulted in not a completely | 10 | big surprise my attempt resulted in not a completely useless piece of software. |
| 11 | useless piece of software. | 11 | |
| 12 | 12 | My initial requirements were quite simple but soon grow into something more | |
| 13 | My initial requirements were quite simple but soon grow into something | 13 | ambitious. And looking back I should have stuck to the simple version. My |
| 14 | more ambitious. And looking back I should have stuck to the simple | 14 | laziness was on my side this time though. Because I haven’t implemented some of |
| 15 | version. My laziness was on my side this time though. Because I haven’t | 15 | the features I now realise I really didn’t need them and they would bog the |
| 16 | implemented some of the features I now realise I really didn’t need them | 16 | whole program and make it be something it was never meant to be. |
| 17 | and they would bog the whole program and make it be something it was | ||
| 18 | never meant to be. | ||
| 19 | 17 | ||
| 20 | My basic requirements were following: | 18 | My basic requirements were following: |
| 21 | 19 | ||
| 22 | - Syntax should be a tiny bit inspired by Rake and Rakefiles. | 20 | - Syntax should be a tiny bit inspired by Rake and Rakefiles. |
| 23 | - Should borrow the overall feel of a unit test experience. | 21 | - Should borrow the overall feel of a unit test experience. |
| 24 | - Using something like Python would be a bit of an overkill. | 22 | - Using something like Python would be a bit of an overkill. |
| 25 | - The program must be statically compiled, so it can run on same | 23 | - The program must be statically compiled, so it can run on same architecture |
| 26 | architecture without libc, musl dependencies or things like that. | 24 | without libc, musl dependencies or things like that. |
| 27 | - Install ruby for rake is a bit overkill and can not be done | 25 | - Install ruby for rake is a bit overkill and can not be done with certain |
| 28 | with certain really lightweight distributions like Alpine | 26 | really lightweight distributions like Alpine Linux. This tool would be usable |
| 29 | Linux. This tool would be usable on such lightweight systems | 27 | on such lightweight systems for remote debugging. |
| 30 | for remote debugging. | 28 | - I want to use it for more than just compiling things. I want to use it as an |
| 31 | - I want to use it for more than just compiling things. I want to | 29 | entry-point into a project, and I want this to help me indirectly document the |
| 32 | use it as an entry-point into a project, and I want this to | 30 | project as well. |
| 33 | help me indirectly document the project as well. | 31 | - It should be an abstraction over bash shell or the default system shell. |
| 34 | - It should be an abstraction over bash shell or the default | ||
| 35 | system shell. | ||
| 36 | - Each task essentially becomes its own shell instance. | 32 | - Each task essentially becomes its own shell instance. |
| 37 | - Must work on Linux and macOS systems. | 33 | - Must work on Linux and macOS systems. |
| 38 | - By default, running `erd` list all the available tasks (when | 34 | - By default, running `erd` list all the available tasks (when I use make, I |
| 39 | I use make, I usually put a disclaimer that you should check | 35 | usually put a disclaimer that you should check Makefile to see all available |
| 40 | Makefile to see all available target). | 36 | target). |
| 41 | - Should support passing arguments when you run it from a shell. | 37 | - Should support passing arguments when you run it from a shell. |
| 42 | - Normal variable as the same as environmental variables. There | 38 | - Normal variable as the same as environmental variables. There is no |
| 43 | is no distinction. Every variable is also essentially an | 39 | distinction. Every variable is also essentially an environment variable and |
| 44 | environment variable and can be used by other programs. | 40 | can be used by other programs. |
| 45 | - State between tasks is not shared, and this makes this “pure” | 41 | - State between tasks is not shared, and this makes this “pure” shell instances. |
| 46 | shell instances. | 42 | - Should be single-threaded for the start and later expanded with `@spawn` |
| 47 | - Should be single-threaded for the start and later expanded | 43 | command. |
| 48 | with `@spawn` command. | ||
| 49 | - Variables behave like macros and are preprocessed before evaluation. | 44 | - Variables behave like macros and are preprocessed before evaluation. |
| 50 | - Should support something like `assure` that would check if | 45 | - Should support something like `assure` that would check if programs like C |
| 51 | programs like C compiler or Python (whatever the project | 46 | compiler or Python (whatever the project requires) are installed on a machine. |
| 52 | requires) are installed on a machine. | ||
| 53 | 47 | ||
| 54 | Quite a reasonable list of requirements. I do this things already in my | 48 | Quite a reasonable list of requirements. I do this things already in my |
| 55 | Makefiles or/and Bash scripts. But I would like to avoid repeating | 49 | Makefiles or/and Bash scripts. But I would like to avoid repeating myself every |
| 56 | myself every time I start working on something new. | 50 | time I start working on something new. |
| 57 | 51 | ||
| 58 | So I started with the following syntax. | 52 | So I started with the following syntax. |
| 59 | 53 | ||
| @@ -111,13 +105,12 @@ end | |||
| 111 | end | 105 | end |
| 112 | ``` | 106 | ``` |
| 113 | 107 | ||
| 114 | One thing that I really like about Errand. Yes, this is what it is | 108 | One thing that I really like about Errand. Yes, this is what it is called. And |
| 115 | called. And it is available at | 109 | it is available at https://git.mitjafelicijan.com/errand.git/about/. Moving |
| 116 | https://git.mitjafelicijan.com/errand.git/about/. Moving on. One thing | 110 | on. One thing that I really like is that a task is a persistent shell. By that I |
| 117 | that I really like is that a task is a persistent shell. By that I mean, | 111 | mean, that the whole task, even if it contains multiple command in one shell. |
| 118 | that the whole task, even if it contains multiple command in one shell. | 112 | In make each line in a target is that and you need to combine lines or add `\` |
| 119 | In make each line in a target is that and you need to combine lines or | 113 | at the end of the line. |
| 120 | add `\` at the end of the line. | ||
| 121 | 114 | ||
| 122 | ```bash | 115 | ```bash |
| 123 | # How you do this things in make. | 116 | # How you do this things in make. |
| @@ -126,43 +119,40 @@ target: | |||
| 126 | python script.py | 119 | python script.py |
| 127 | ``` | 120 | ``` |
| 128 | 121 | ||
| 129 | This solves this problem. Consider each task and what is being executed | 122 | This solves this problem. Consider each task and what is being executed in that |
| 130 | in that task a shell that will only close when all the tasks are | 123 | task a shell that will only close when all the tasks are completed. |
| 131 | completed. | 124 | |
| 132 | 125 | By self-documenting I mean that if you are in a directory with `Errandfile` in, | |
| 133 | By self-documenting I mean that if you are in a directory with | 126 | if you only type `erd` and press enter it should by default display all the |
| 134 | `Errandfile` in, if you only type `erd` and press enter it should by | 127 | possible targets. In make i was doing this by having a first target be something |
| 135 | default display all the possible targets. In make i was doing this by | 128 | like `default` that echos the message “Check Makefile for all available target.” |
| 136 | having a first target be something like `default` that echos the message | 129 | Because all of the tasks in Errand require a message I use that to display let’s |
| 137 | “Check Makefile for all available target.” Because all of the tasks in | 130 | call it table of contents. |
| 138 | Errand require a message I use that to display let’s call it table of | 131 | |
| 139 | contents. | 132 | Because I don’t use any external dependencies this whole thing can be statically |
| 140 | 133 | compiled. So that also checked one of the boxes. | |
| 141 | Because I don’t use any external dependencies this whole thing can be | 134 | |
| 142 | statically compiled. So that also checked one of the boxes. | 135 | It works on Linux and on a Mac so that’s also a bonus. I don’t believe this |
| 143 | 136 | would work on Windows machines because of the way that I use shell instances. By | |
| 144 | It works on Linux and on a Mac so that’s also a bonus. I don’t believe | 137 | you could use something like Windows Subsystem for Linux and run it in |
| 145 | this would work on Windows machines because of the way that I use shell | 138 | there. That is a valid option. |
| 146 | instances. By you could use something like Windows Subsystem for Linux | 139 | |
| 147 | and run it in there. That is a valid option. | 140 | To finish this essay off, how was it to use it in “real life”. I have to be |
| 148 | 141 | honest. Some of the missing features still bother me. `@dotenv` directive is | |
| 149 | To finish this essay off, how was it to use it in “real life”. I have to | 142 | still missing and I need to implement this ASAP. |
| 150 | be honest. Some of the missing features still bother me. `@dotenv` | 143 | |
| 151 | directive is still missing and I need to implement this ASAP. | 144 | Another thing that needs to happen is support for streaming output. Currently |
| 152 | 145 | commands like `docker-compose` that runs in foreground mode is not compatible | |
| 153 | Another thing that needs to happen is support for streaming output. | 146 | with Errand. So commands that stream output are an issue. I need to revisit how |
| 154 | Currently commands like `docker-compose` that runs in foreground mode is | 147 | I initiate shell and how I read stdout and stderr. But that shouldn’t be a |
| 155 | not compatible with Errand. So commands that stream output are an issue. | 148 | problem. |
| 156 | I need to revisit how I initiate shell and how I read stdout and stderr. | 149 | |
| 157 | But that shouldn’t be a problem. | 150 | I have been very satisfied with this thing. I am pleasantly surprised by how |
| 158 | 151 | useful it is. I really wanted to test this in the wild before I commit to it. I | |
| 159 | I have been very satisfied with this thing. I am pleasantly surprised by | 152 | have more abandoned project than Google and it’s bringing a massive shame to my |
| 160 | how useful it is. I really wanted to test this in the wild before I | 153 | family at this point. So I wanted to be sure that this is even useful. And it |
| 161 | commit to it. I have more abandoned project than Google and it’s | 154 | actually is. Quite surprised at myself. |
| 162 | bringing a massive shame to my family at this point. So I wanted to be | 155 | |
| 163 | sure that this is even useful. And it actually is. Quite surprised at | 156 | I really need to package this now and write proper docs. And maybe rewrite |
| 164 | myself. | 157 | tokeniser. Its atrocious right now. Site to behold! But that is an issue for |
| 165 | 158 | another time. | |
| 166 | I really need to package this now and write proper docs. And maybe | ||
| 167 | rewrite tokeniser. Its atrocious right now. Site to behold! But that is | ||
| 168 | an issue for another time. | ||
diff --git a/static/general/index.css b/static/general/index.css index 9c274d6..3f2a85e 100644 --- a/static/general/index.css +++ b/static/general/index.css | |||
| @@ -1 +1 @@ | |||
| /*! tailwindcss v3.3.2 | MIT License | https://tailwindcss.com*/*,:after,:before{box-sizing:border-box;border:0 solid #e5e7eb}:after,:before{--tw-content:""}html{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;font-feature-settings:normal;font-variation-settings:normal}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,pre,samp{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:initial}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-size:100%;font-weight:inherit;line-height:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button;background-color:initial;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:initial}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dd,dl,figure,h1,h2,h3,h4,h5,h6,hr,p,pre{margin:0}fieldset{margin:0}fieldset,legend{padding:0}menu,ol,ul{list-style:none;margin:0;padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}[role=button],button{cursor:pointer}:disabled{cursor:default}audio,canvas,embed,iframe,img,object,svg,video{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]{display:none}*,::backdrop,:after,:before{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:#3b82f680;--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: }.mx-auto{margin-left:auto;margin-right:auto}.my-12{margin-top:3rem;margin-bottom:3rem}.mb-1{margin-bottom:.25rem}.mb-10{margin-bottom:2.5rem}.mb-12{margin-bottom:3rem}.mb-2{margin-bottom:.5rem}.mb-4{margin-bottom:1rem}.mb-5{margin-bottom:1.25rem}.mb-6{margin-bottom:1.5rem}.mb-8{margin-bottom:2rem}.ml-6{margin-left:1.5rem}.mt-4{margin-top:1rem}.mt-6{margin-top:1.5rem}.block{display:block}.inline-block{display:inline-block}.flex{display:flex}.inline-flex{display:inline-flex}.contents{display:contents}.hidden{display:none}.h-full{height:100%}.w-full{width:100%}.flex-grow{flex-grow:1}.list-disc{list-style-type:disc}.flex-row{flex-direction:row}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-center{align-items:center}.gap-1{gap:.25rem}.gap-2{gap:.5rem}.rounded{border-radius:.25rem}.border-0{border-width:0}.border-2{border-width:2px}.border-gray-100{--tw-border-opacity:1;border-color:rgb(243 244 246/var(--tw-border-opacity))}.bg-gray-100{--tw-bg-opacity:1;background-color:rgb(243 244 246/var(--tw-bg-opacity))}.bg-orange-600{--tw-bg-opacity:1;background-color:rgb(234 88 12/var(--tw-bg-opacity))}.px-1{padding-left:.25rem;padding-right:.25rem}.px-1\.5{padding-left:.375rem;padding-right:.375rem}.px-2{padding-left:.5rem;padding-right:.5rem}.px-3{padding-left:.75rem;padding-right:.75rem}.px-6{padding-left:1.5rem;padding-right:1.5rem}.py-1{padding-top:.25rem;padding-bottom:.25rem}.py-2{padding-top:.5rem;padding-bottom:.5rem}.py-4{padding-top:1rem;padding-bottom:1rem}.pb-16{padding-bottom:4rem}.text-2xl{font-size:1.5rem;line-height:2rem}.text-4xl{font-size:2.25rem;line-height:2.5rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xl{font-size:1.25rem;line-height:1.75rem}.text-xs{font-size:.75rem;line-height:1rem}.font-bold{font-weight:700}.font-medium{font-weight:500}.font-semibold{font-weight:600}.italic{font-style:italic}.leading-relaxed{line-height:1.625}.text-gray-400{--tw-text-opacity:1;color:rgb(156 163 175/var(--tw-text-opacity))}.text-gray-500{--tw-text-opacity:1;color:rgb(107 114 128/var(--tw-text-opacity))}.text-gray-600{--tw-text-opacity:1;color:rgb(75 85 99/var(--tw-text-opacity))}.text-white{--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity))}.underline{text-decoration-line:underline}.no-underline{text-decoration-line:none}.underline-offset-2{text-underline-offset:2px}.container-blog{max-width:700px}::selection{--tw-bg-opacity:1;background-color:rgb(254 249 195/var(--tw-bg-opacity));--tw-text-opacity:1;color:rgb(0 0 0/var(--tw-text-opacity))}::-moz-selection{--tw-bg-opacity:1;background-color:rgb(254 249 195/var(--tw-bg-opacity));--tw-text-opacity:1;color:rgb(0 0 0/var(--tw-text-opacity))}.blue,a:hover{color:blue}article.single h2{margin-bottom:2rem}article.single h2,article.single.note h2{margin-top:2rem;font-size:1.5rem;line-height:2rem;font-weight:700;line-height:1.25}article.single.note h2{margin-bottom:.25rem}article.single h3{font-size:1.25rem}article.single h3,article.single h4{margin-bottom:1rem;margin-top:2rem;line-height:1.75rem;font-weight:700;line-height:1.25}article.single h4{font-size:1.125rem}article.single p{margin-bottom:1.25rem}article.single a{text-decoration-line:underline;text-underline-offset:2px}article.single a:hover{--tw-bg-opacity:1;background-color:rgb(254 249 195/var(--tw-bg-opacity))}article.single .content blockquote{background-image:url(/general/alert-light.svg);background-size:30px 30px;background-repeat:no-repeat;background-position:0 5px;margin-top:2rem;margin-bottom:2rem;padding-left:3rem}article.single .content blockquote p{margin-bottom:.5rem}article.single img{margin-top:2rem;margin-bottom:2rem;image-rendering:crisp-edges;image-rendering:-webkit-optimize-contrast}article.single img,article.single video{width:100%;border-radius:.25rem;--tw-bg-opacity:1!important;background-color:rgb(249 250 251/var(--tw-bg-opacity))!important}article.single audio{margin-bottom:1.5rem;width:100%}article.single code{background-color:rgb(254 249 195/var(--tw-bg-opacity))}article.single code,article.single.note code{border-radius:.25rem;--tw-bg-opacity:1;padding:.25rem .5rem;font-size:.75rem;line-height:1rem;font-weight:500}article.single.note code{background-color:rgb(243 244 246/var(--tw-bg-opacity))}article.single pre{margin-bottom:1.5rem;overflow-x:auto;border-radius:.25rem;--tw-bg-opacity:1!important;background-color:rgb(249 250 251/var(--tw-bg-opacity))!important;padding:1rem;font-size:.75rem;line-height:1rem}article.single pre code,article.single.note pre code{background:unset;padding:unset;line-height:1.625}article.single table{margin-bottom:1rem;width:100%;border-collapse:collapse;border-width:1px;--tw-border-opacity:1;border-color:rgb(0 0 0/var(--tw-border-opacity))}article.single table td,article.single table th,article.single table tr{border-width:1px;padding:.5rem 1rem;text-align:left}article.single .content ul{margin-bottom:1.5rem;list-style-type:disc;padding-left:1.5rem}@media (min-width:768px){article.single .content ul{padding-left:2.5rem}}article.single .content ol{margin-bottom:1.5rem;list-style-type:decimal;padding-left:2rem}@media (min-width:768px){article.single .content ol{padding-left:2.5rem}}article.single #TableOfContents{margin-bottom:2.5rem;margin-left:1rem;line-height:1.625}article.single #TableOfContents ul{list-style-type:decimal;padding-left:1rem}@media (min-width:768px){article.single #TableOfContents ul{padding-left:1.5rem}}article.single .content ul ul{margin-bottom:auto}article.single .katex-display{margin-top:2.5rem;margin-bottom:2.5rem}article.single .ll-iframe{border-radius:.25rem;--tw-bg-opacity:1;background-color:rgb(243 244 246/var(--tw-bg-opacity))}article.single .ll-iframe:before{display:flex;height:100%}@keyframes pulse{50%{opacity:.5}}article.single .ll-iframe:before{animation:pulse 2s cubic-bezier(.4,0,.6,1) infinite;cursor:pointer;align-items:center;justify-content:center;border-radius:.25rem;border-width:2px;--tw-border-opacity:1;border-color:rgb(209 213 219/var(--tw-border-opacity));font-size:.875rem;line-height:1.25rem;font-weight:500;content:"Click here to load resource…"}article.single .ll-iframe.empty:before{content:none}.hover\:bg-yellow-100:hover{--tw-bg-opacity:1;background-color:rgb(254 249 195/var(--tw-bg-opacity))}.hover\:text-gray-800:hover{--tw-text-opacity:1;color:rgb(31 41 55/var(--tw-text-opacity))}.hover\:underline:hover{text-decoration-line:underline}@media (min-width:768px){.md\:mb-0{margin-bottom:0}.md\:block{display:block}.md\:inline-block{display:inline-block}.md\:w-auto{width:auto}.md\:flex-row{flex-direction:row}.md\:p-0{padding:0}} \ No newline at end of file | /*! tailwindcss v3.3.2 | MIT License | https://tailwindcss.com*/*,:after,:before{box-sizing:border-box;border:0 solid #e5e7eb}:after,:before{--tw-content:""}html{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;font-feature-settings:normal;font-variation-settings:normal}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,pre,samp{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:initial}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-size:100%;font-weight:inherit;line-height:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button;background-color:initial;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:initial}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dd,dl,figure,h1,h2,h3,h4,h5,h6,hr,p,pre{margin:0}fieldset{margin:0}fieldset,legend{padding:0}menu,ol,ul{list-style:none;margin:0;padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}[role=button],button{cursor:pointer}:disabled{cursor:default}audio,canvas,embed,iframe,img,object,svg,video{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]{display:none}*,::backdrop,:after,:before{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:#3b82f680;--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: }.relative{position:relative}.mx-auto{margin-left:auto;margin-right:auto}.my-12{margin-top:3rem;margin-bottom:3rem}.mb-1{margin-bottom:.25rem}.mb-10{margin-bottom:2.5rem}.mb-12{margin-bottom:3rem}.mb-2{margin-bottom:.5rem}.mb-4{margin-bottom:1rem}.mb-5{margin-bottom:1.25rem}.mb-6{margin-bottom:1.5rem}.mb-8{margin-bottom:2rem}.ml-6{margin-left:1.5rem}.mt-4{margin-top:1rem}.mt-6{margin-top:1.5rem}.block{display:block}.inline-block{display:inline-block}.flex{display:flex}.inline-flex{display:inline-flex}.contents{display:contents}.hidden{display:none}.h-full{height:100%}.w-full{width:100%}.flex-grow{flex-grow:1}.list-disc{list-style-type:disc}.flex-row{flex-direction:row}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-center{align-items:center}.gap-1{gap:.25rem}.gap-2{gap:.5rem}.rounded{border-radius:.25rem}.border-0{border-width:0}.border-2{border-width:2px}.border-gray-100{--tw-border-opacity:1;border-color:rgb(243 244 246/var(--tw-border-opacity))}.bg-gray-100{--tw-bg-opacity:1;background-color:rgb(243 244 246/var(--tw-bg-opacity))}.bg-orange-600{--tw-bg-opacity:1;background-color:rgb(234 88 12/var(--tw-bg-opacity))}.px-1{padding-left:.25rem;padding-right:.25rem}.px-1\.5{padding-left:.375rem;padding-right:.375rem}.px-2{padding-left:.5rem;padding-right:.5rem}.px-3{padding-left:.75rem;padding-right:.75rem}.px-6{padding-left:1.5rem;padding-right:1.5rem}.py-1{padding-top:.25rem;padding-bottom:.25rem}.py-2{padding-top:.5rem;padding-bottom:.5rem}.py-4{padding-top:1rem;padding-bottom:1rem}.pb-16{padding-bottom:4rem}.text-2xl{font-size:1.5rem;line-height:2rem}.text-4xl{font-size:2.25rem;line-height:2.5rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xl{font-size:1.25rem;line-height:1.75rem}.text-xs{font-size:.75rem;line-height:1rem}.font-bold{font-weight:700}.font-medium{font-weight:500}.font-semibold{font-weight:600}.italic{font-style:italic}.leading-relaxed{line-height:1.625}.text-gray-400{--tw-text-opacity:1;color:rgb(156 163 175/var(--tw-text-opacity))}.text-gray-500{--tw-text-opacity:1;color:rgb(107 114 128/var(--tw-text-opacity))}.text-gray-600{--tw-text-opacity:1;color:rgb(75 85 99/var(--tw-text-opacity))}.text-white{--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity))}.underline{text-decoration-line:underline}.no-underline{text-decoration-line:none}.underline-offset-2{text-underline-offset:2px}.container-blog{max-width:700px}::selection{--tw-bg-opacity:1;background-color:rgb(254 249 195/var(--tw-bg-opacity));--tw-text-opacity:1;color:rgb(0 0 0/var(--tw-text-opacity))}::-moz-selection{--tw-bg-opacity:1;background-color:rgb(254 249 195/var(--tw-bg-opacity));--tw-text-opacity:1;color:rgb(0 0 0/var(--tw-text-opacity))}.blue,a:hover{color:blue}article.single h2{margin-bottom:2rem}article.single h2,article.single.note h2{margin-top:2rem;font-size:1.5rem;line-height:2rem;font-weight:700;line-height:1.25}article.single.note h2{margin-bottom:.25rem}article.single h3{font-size:1.25rem}article.single h3,article.single h4{margin-bottom:1rem;margin-top:2rem;line-height:1.75rem;font-weight:700;line-height:1.25}article.single h4{font-size:1.125rem}article.single p{margin-bottom:1.25rem}article.single a{text-decoration-line:underline;text-underline-offset:2px}article.single a:hover{--tw-bg-opacity:1;background-color:rgb(254 249 195/var(--tw-bg-opacity))}article.single .content blockquote{background-image:url(/general/alert-light.svg);background-size:30px 30px;background-repeat:no-repeat;background-position:0 5px;margin-top:2rem;margin-bottom:2rem;padding-left:3rem}article.single .content blockquote p{margin-bottom:.5rem}article.single figure{margin-top:2rem;margin-bottom:2rem}article.single figure figcaption{margin-top:.25rem;text-align:center;font-style:italic}article.single img{image-rendering:crisp-edges;image-rendering:-webkit-optimize-contrast}article.single img,article.single video{width:100%;border-radius:.25rem;--tw-bg-opacity:1!important;background-color:rgb(249 250 251/var(--tw-bg-opacity))!important}article.single audio{margin-bottom:1.5rem;width:100%}article.single code{background-color:rgb(254 249 195/var(--tw-bg-opacity))}article.single code,article.single.note code{border-radius:.25rem;--tw-bg-opacity:1;padding:.25rem .5rem;font-size:.75rem;line-height:1rem;font-weight:500}article.single.note code{background-color:rgb(243 244 246/var(--tw-bg-opacity))}article.single pre{margin-bottom:1.5rem;overflow-x:auto;border-radius:.25rem;--tw-bg-opacity:1!important;background-color:rgb(249 250 251/var(--tw-bg-opacity))!important;padding:1rem;font-size:.75rem;line-height:1rem}article.single pre code,article.single.note pre code{background:unset;padding:unset;line-height:1.625}article.single table{margin-bottom:1rem;width:100%;border-collapse:collapse;border-width:1px;--tw-border-opacity:1;border-color:rgb(0 0 0/var(--tw-border-opacity))}article.single table td,article.single table th,article.single table tr{border-width:1px;padding:.5rem 1rem;text-align:left}article.single .content ul{margin-bottom:1.5rem;list-style-type:disc;padding-left:1.5rem}@media (min-width:768px){article.single .content ul{padding-left:2.5rem}}article.single .content ol{margin-bottom:1.5rem;list-style-type:decimal;padding-left:2rem}@media (min-width:768px){article.single .content ol{padding-left:2.5rem}}article.single #TableOfContents{margin-bottom:2.5rem;margin-left:1rem;line-height:1.625}article.single #TableOfContents ul{list-style-type:decimal;padding-left:1rem}@media (min-width:768px){article.single #TableOfContents ul{padding-left:1.5rem}}article.single .content ul ul{margin-bottom:auto}article.single .katex-display{margin-top:2.5rem;margin-bottom:2.5rem}article.single .ll-iframe{border-radius:.25rem;--tw-bg-opacity:1;background-color:rgb(243 244 246/var(--tw-bg-opacity))}article.single .ll-iframe:before{display:flex;height:100%}@keyframes pulse{50%{opacity:.5}}article.single .ll-iframe:before{animation:pulse 2s cubic-bezier(.4,0,.6,1) infinite;cursor:pointer;align-items:center;justify-content:center;border-radius:.25rem;border-width:2px;--tw-border-opacity:1;border-color:rgb(209 213 219/var(--tw-border-opacity));font-size:.875rem;line-height:1.25rem;font-weight:500;content:"Click here to load resource…"}article.single .ll-iframe.empty:before{content:none}.hover\:bg-yellow-100:hover{--tw-bg-opacity:1;background-color:rgb(254 249 195/var(--tw-bg-opacity))}.hover\:text-gray-800:hover{--tw-text-opacity:1;color:rgb(31 41 55/var(--tw-text-opacity))}.hover\:underline:hover{text-decoration-line:underline}@media (min-width:768px){.md\:mb-0{margin-bottom:0}.md\:block{display:block}.md\:inline-block{display:inline-block}.md\:w-auto{width:auto}.md\:flex-row{flex-direction:row}.md\:p-0{padding:0}} \ No newline at end of file | ||
diff --git a/themes/simple/layouts/_default/_markup/render-image.html b/themes/simple/layouts/_default/_markup/render-image.html index 6f46efa..d3df1fd 100644 --- a/themes/simple/layouts/_default/_markup/render-image.html +++ b/themes/simple/layouts/_default/_markup/render-image.html | |||
| @@ -5,6 +5,7 @@ | |||
| 5 | <img | 5 | <img |
| 6 | loading="lazy" | 6 | loading="lazy" |
| 7 | src="{{ .Destination }}?v={{ $cachebuster }}" | 7 | src="{{ .Destination }}?v={{ $cachebuster }}" |
| 8 | alt="{{ .Text }}" title="{{ .Text }}"> | 8 | alt="{{ .Text }}" title="{{ .Text }}"> |
| 9 | </a> | 9 | </a> |
| 10 | <figcaption>{{ .Text }}</figcaption> | ||
| 10 | </figure> | 11 | </figure> |
diff --git a/themes/simple/static/css/tailwind.css b/themes/simple/static/css/tailwind.css index b99c7fc..51b922c 100644 --- a/themes/simple/static/css/tailwind.css +++ b/themes/simple/static/css/tailwind.css | |||
| @@ -6,153 +6,161 @@ | |||
| 6 | 6 | ||
| 7 | /* Container */ | 7 | /* Container */ |
| 8 | .container-blog { | 8 | .container-blog { |
| 9 | max-width: 700px; | 9 | max-width: 700px; |
| 10 | } | 10 | } |
| 11 | 11 | ||
| 12 | /* User text selection */ | 12 | /* User text selection */ |
| 13 | ::selection { | 13 | ::selection { |
| 14 | @apply bg-yellow-100 text-black; | 14 | @apply bg-yellow-100 text-black; |
| 15 | } | 15 | } |
| 16 | 16 | ||
| 17 | ::-moz-selection { | 17 | ::-moz-selection { |
| 18 | @apply bg-yellow-100 text-black; | 18 | @apply bg-yellow-100 text-black; |
| 19 | } | 19 | } |
| 20 | 20 | ||
| 21 | /* Helpers */ | 21 | /* Helpers */ |
| 22 | 22 | ||
| 23 | a:hover { | 23 | a:hover { |
| 24 | color: blue; | 24 | color: blue; |
| 25 | } | 25 | } |
| 26 | 26 | ||
| 27 | .blue { | 27 | .blue { |
| 28 | color: blue; | 28 | color: blue; |
| 29 | } | 29 | } |
| 30 | 30 | ||
| 31 | /* Headings */ | 31 | /* Headings */ |
| 32 | article.single h2 { | 32 | article.single h2 { |
| 33 | @apply text-2xl font-bold mb-8 mt-8 leading-tight; | 33 | @apply text-2xl font-bold mb-8 mt-8 leading-tight; |
| 34 | } | 34 | } |
| 35 | 35 | ||
| 36 | article.single.note h2 { | 36 | article.single.note h2 { |
| 37 | @apply text-2xl font-bold mb-1 mt-8 leading-tight; | 37 | @apply text-2xl font-bold mb-1 mt-8 leading-tight; |
| 38 | } | 38 | } |
| 39 | 39 | ||
| 40 | article.single h3 { | 40 | article.single h3 { |
| 41 | @apply text-xl font-bold mb-4 mt-8 leading-tight; | 41 | @apply text-xl font-bold mb-4 mt-8 leading-tight; |
| 42 | } | 42 | } |
| 43 | 43 | ||
| 44 | article.single h4 { | 44 | article.single h4 { |
| 45 | @apply text-lg font-bold mb-4 mt-8 leading-tight; | 45 | @apply text-lg font-bold mb-4 mt-8 leading-tight; |
| 46 | } | 46 | } |
| 47 | 47 | ||
| 48 | /* Paragraph */ | 48 | /* Paragraph */ |
| 49 | article.single p { | 49 | article.single p { |
| 50 | @apply mb-5; | 50 | @apply mb-5; |
| 51 | } | 51 | } |
| 52 | 52 | ||
| 53 | /* Links */ | 53 | /* Links */ |
| 54 | article.single a { | 54 | article.single a { |
| 55 | @apply underline-offset-2 underline hover:bg-yellow-100; | 55 | @apply underline-offset-2 underline hover:bg-yellow-100; |
| 56 | } | 56 | } |
| 57 | 57 | ||
| 58 | /* Blockquote */ | 58 | /* Blockquote */ |
| 59 | article.single .content blockquote { | 59 | article.single .content blockquote { |
| 60 | background-image: url('/general/alert-light.svg'); | 60 | background-image: url('/general/alert-light.svg'); |
| 61 | background-size: 30px 30px; | 61 | background-size: 30px 30px; |
| 62 | background-repeat: no-repeat; | 62 | background-repeat: no-repeat; |
| 63 | background-position: 0 5px; | 63 | background-position: 0 5px; |
| 64 | @apply pl-12 my-8; | 64 | @apply pl-12 my-8; |
| 65 | } | 65 | } |
| 66 | 66 | ||
| 67 | article.single .content blockquote p { | 67 | article.single .content blockquote p { |
| 68 | @apply mb-2; | 68 | @apply mb-2; |
| 69 | } | 69 | } |
| 70 | 70 | ||
| 71 | /* Media: Images, audio, video */ | 71 | /* Media: Images, audio, video */ |
| 72 | article.single figure { | ||
| 73 | @apply my-8; | ||
| 74 | } | ||
| 75 | |||
| 76 | article.single figure figcaption { | ||
| 77 | @apply text-center italic mt-1; | ||
| 78 | } | ||
| 79 | |||
| 72 | article.single img { | 80 | article.single img { |
| 73 | @apply rounded w-full !bg-gray-50 my-8; | 81 | @apply rounded w-full !bg-gray-50; |
| 74 | 82 | ||
| 75 | image-rendering: crisp-edges; | 83 | image-rendering: crisp-edges; |
| 76 | image-rendering: -webkit-optimize-contrast; | 84 | image-rendering: -webkit-optimize-contrast; |
| 77 | } | 85 | } |
| 78 | 86 | ||
| 79 | article.single video { | 87 | article.single video { |
| 80 | @apply rounded w-full !bg-gray-50; | 88 | @apply rounded w-full !bg-gray-50; |
| 81 | } | 89 | } |
| 82 | 90 | ||
| 83 | article.single audio { | 91 | article.single audio { |
| 84 | @apply w-full mb-6; | 92 | @apply w-full mb-6; |
| 85 | } | 93 | } |
| 86 | 94 | ||
| 87 | /* Code */ | 95 | /* Code */ |
| 88 | article.single code { | 96 | article.single code { |
| 89 | @apply bg-yellow-100 rounded px-2 py-1 text-xs font-medium; | 97 | @apply bg-yellow-100 rounded px-2 py-1 text-xs font-medium; |
| 90 | } | 98 | } |
| 91 | 99 | ||
| 92 | article.single.note code { | 100 | article.single.note code { |
| 93 | @apply bg-gray-100 rounded px-2 py-1 text-xs font-medium; | 101 | @apply bg-gray-100 rounded px-2 py-1 text-xs font-medium; |
| 94 | } | 102 | } |
| 95 | 103 | ||
| 96 | article.single pre { | 104 | article.single pre { |
| 97 | @apply !bg-gray-50 rounded text-xs p-4 mb-6 overflow-x-auto; | 105 | @apply !bg-gray-50 rounded text-xs p-4 mb-6 overflow-x-auto; |
| 98 | } | 106 | } |
| 99 | 107 | ||
| 100 | article.single pre code, | 108 | article.single pre code, |
| 101 | article.single.note pre code { | 109 | article.single.note pre code { |
| 102 | background: unset; | 110 | background: unset; |
| 103 | padding: unset; | 111 | padding: unset; |
| 104 | @apply leading-relaxed; | 112 | @apply leading-relaxed; |
| 105 | } | 113 | } |
| 106 | 114 | ||
| 107 | /* Tables */ | 115 | /* Tables */ |
| 108 | article.single table { | 116 | article.single table { |
| 109 | @apply w-full border border-black border-collapse mb-4; | 117 | @apply w-full border border-black border-collapse mb-4; |
| 110 | } | 118 | } |
| 111 | 119 | ||
| 112 | article.single table tr, | 120 | article.single table tr, |
| 113 | article.single table td, | 121 | article.single table td, |
| 114 | article.single table th { | 122 | article.single table th { |
| 115 | @apply px-4 py-2 border text-left; | 123 | @apply px-4 py-2 border text-left; |
| 116 | } | 124 | } |
| 117 | 125 | ||
| 118 | /* Unordered list */ | 126 | /* Unordered list */ |
| 119 | article.single .content ul { | 127 | article.single .content ul { |
| 120 | @apply list-disc pl-6 md:pl-10 mb-6; | 128 | @apply list-disc pl-6 md:pl-10 mb-6; |
| 121 | } | 129 | } |
| 122 | 130 | ||
| 123 | /* Ordered list */ | 131 | /* Ordered list */ |
| 124 | article.single .content ol { | 132 | article.single .content ol { |
| 125 | @apply list-decimal pl-8 md:pl-10 mb-6; | 133 | @apply list-decimal pl-8 md:pl-10 mb-6; |
| 126 | } | 134 | } |
| 127 | 135 | ||
| 128 | /* Table of contents */ | 136 | /* Table of contents */ |
| 129 | article.single #TableOfContents { | 137 | article.single #TableOfContents { |
| 130 | @apply mb-10 ml-4 leading-relaxed; | 138 | @apply mb-10 ml-4 leading-relaxed; |
| 131 | } | 139 | } |
| 132 | article.single #TableOfContents ul { | 140 | article.single #TableOfContents ul { |
| 133 | @apply list-decimal pl-4 md:pl-6; | 141 | @apply list-decimal pl-4 md:pl-6; |
| 134 | } | 142 | } |
| 135 | 143 | ||
| 136 | /* Lists */ | 144 | /* Lists */ |
| 137 | article.single .content ul ul { | 145 | article.single .content ul ul { |
| 138 | margin-bottom: auto; | 146 | margin-bottom: auto; |
| 139 | } | 147 | } |
| 140 | 148 | ||
| 141 | /* Katex */ | 149 | /* Katex */ |
| 142 | article.single .katex-display { | 150 | article.single .katex-display { |
| 143 | @apply my-10; | 151 | @apply my-10; |
| 144 | } | 152 | } |
| 145 | 153 | ||
| 146 | /* Lazy loading of iframes */ | 154 | /* Lazy loading of iframes */ |
| 147 | article.single .ll-iframe { | 155 | article.single .ll-iframe { |
| 148 | @apply bg-gray-100 rounded; | 156 | @apply bg-gray-100 rounded; |
| 149 | } | 157 | } |
| 150 | 158 | ||
| 151 | article.single .ll-iframe::before { | 159 | article.single .ll-iframe::before { |
| 152 | @apply h-full flex border-2 border-gray-300 rounded justify-center items-center font-medium text-sm cursor-pointer animate-pulse; | 160 | @apply h-full flex border-2 border-gray-300 rounded justify-center items-center font-medium text-sm cursor-pointer animate-pulse; |
| 153 | content: 'Click here to load resource…'; | 161 | content: 'Click here to load resource…'; |
| 154 | } | 162 | } |
| 155 | 163 | ||
| 156 | article.single .ll-iframe.empty::before { | 164 | article.single .ll-iframe.empty::before { |
| 157 | content: none; | 165 | content: none; |
| 158 | } | 166 | } |
