Compare commits

25 Commits

Author SHA1 Message Date
f31552e791 Use vmax instead of vh
All checks were successful
Build and Deploy Zola Website / build_and_deploy (push) Successful in 15s
Build Zola Website / build (pull_request) Successful in 23s
2024-12-18 12:55:30 +01:00
000bb3ea47 Fix visible content in navbar
All checks were successful
Build and Deploy Zola Website / build_and_deploy (push) Successful in 15s
Build Zola Website / build (pull_request) Successful in 21s
2024-12-15 08:32:34 +01:00
297f96ab99 Added postbuild script to the Gitea Action
All checks were successful
Build and Deploy Zola Website / build_and_deploy (push) Successful in 13s
Build Zola Website / build (pull_request) Successful in 20s
2024-12-15 08:18:35 +01:00
3112316e7d Added execute permissions to the postbuild script 2024-12-15 08:18:10 +01:00
1ca991e4b9 Added: postbuild script 2024-12-15 08:14:54 +01:00
c827757fb8 Added: burger menu for mobile views
All checks were successful
Build and Deploy Zola Website / build_and_deploy (push) Successful in 14s
Build Zola Website / build (pull_request) Successful in 21s
2024-12-15 08:09:10 +01:00
01c994aa13 Added auto-awning-close and walauncher projects
All checks were successful
Build and Deploy Zola Website / build_and_deploy (push) Successful in 13s
Build Zola Website / build (pull_request) Successful in 20s
2024-12-15 03:57:28 +01:00
1de4bf249b Added: hr under the h1 in posts and projects template
All checks were successful
Build and Deploy Zola Website / build_and_deploy (push) Successful in 14s
Build Zola Website / build (pull_request) Successful in 20s
2024-12-15 03:52:41 +01:00
28c29f0d30 Fix code overflow
All checks were successful
Build and Deploy Zola Website / build_and_deploy (push) Successful in 13s
Build Zola Website / build (pull_request) Successful in 20s
2024-12-14 23:09:30 +01:00
8a832250a0 New post: Creating a Language-Specific Jellyfin Library
All checks were successful
Build and Deploy Zola Website / build_and_deploy (push) Successful in 14s
Build Zola Website / build (pull_request) Successful in 20s
2024-12-14 19:52:23 +01:00
225f2af48b Tracking added
All checks were successful
Build and Deploy Zola Website / build_and_deploy (push) Successful in 13s
Build Zola Website / build (pull_request) Successful in 28s
2024-11-16 20:27:28 +01:00
2144038970 Rewrite title and description for jellyfin post
All checks were successful
Build and Deploy Zola Website / build_and_deploy (push) Successful in 17s
Build Zola Website / build (pull_request) Successful in 24s
2024-10-17 14:03:35 +02:00
512a810122 New post: how i fixed cs2 4:3 resolution 2024-10-17 13:59:25 +02:00
2e5696f767 Added: copy text button
All checks were successful
Build and Deploy Zola Website / build_and_deploy (push) Successful in 28s
Build Zola Website / build (pull_request) Successful in 35s
2024-10-15 11:11:08 +02:00
1751b590aa Text align left
All checks were successful
Build and Deploy Zola Website / build_and_deploy (push) Successful in 16s
Build Zola Website / build (pull_request) Successful in 21s
2024-10-14 19:24:42 +02:00
a95f13943f CSS formatted
All checks were successful
Build and Deploy Zola Website / build_and_deploy (push) Successful in 16s
Build Zola Website / build (pull_request) Successful in 23s
2024-10-14 17:15:08 +02:00
7f23f234cd Changed ancher color 2024-10-14 17:13:49 +02:00
b227a41a43 Zola workflow updated
All checks were successful
Build and Deploy Zola Website / build_and_deploy (push) Successful in 30s
Build Zola Website / build (pull_request) Successful in 27s
2024-10-14 17:01:20 +02:00
bf5f265116 Design improvments 2024-10-14 16:52:45 +02:00
1cf12f91f0 Added border radius to code, meta description 2024-10-14 16:10:17 +02:00
00eec8be70 CSS redesign stuff, other things idk 2024-10-14 01:15:41 +02:00
542e432596 Jellyfin post 2024-10-12 22:45:43 +02:00
0791f417f3 Core for the posts section 2024-10-03 02:45:58 +02:00
2439dfa78d Added: biome for formatting, Makefile
All checks were successful
Build and Deploy Zola Website / build_and_deploy (push) Successful in 36s
Build Zola Website / build (pull_request) Successful in 17s
2024-06-03 00:23:19 +02:00
e0248abb46 Revert "Changes for master"
This reverts commit b022a4ae37.
2024-06-03 00:10:28 +02:00
33 changed files with 248 additions and 539 deletions

View File

@@ -4,9 +4,6 @@ on: pull_request
jobs: jobs:
build: build:
# Skip if PR base is master/dev
if: github.base_ref != 'master' && github.base_ref != 'dev'
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:

2
.gitignore vendored
View File

@@ -1,3 +1 @@
public/ public/
!static/public/
*.swp

View File

@@ -1,41 +1,10 @@
# -------- Config -------- all: clean format build
SHELL := /bin/sh
ZOLA ?= zola format:
BIOME ?= npx biome biome format --write .
BUILD_DIR := public build:
zola build
# -------- Targets --------
.PHONY: help serve build clean format lint fix fix-unsafe check ci
help: ## Show this help
@awk 'BEGIN{FS":.*##"; printf "\nTargets:\n"} /^[a-zA-Z0-9_.-]+:.*##/{printf " \033[36m%-14s\033[0m %s\n", $$1, $$2}' $(MAKEFILE_LIST); echo
serve: ## Run Zola dev server (http://127.0.0.1:1111)
$(ZOLA) serve
build: ## Build site into ./public
$(ZOLA) build
clean: ## Remove ./public
rm -rf "$(BUILD_DIR)"
format: ## Format JS/JSON/CSS with Biome (no linting)
$(BIOME) format --write .
lint: ## Lint with Biome (no writes)
$(BIOME) ci .
fix: ## Lint+auto-fix safe changes with Biome
$(BIOME) check --write .
fix-unsafe: ## Lint+auto-fix incl. unsafe (e.g., template literals)
$(BIOME) check --write --unsafe .
check: ## Zola link/content checks
$(ZOLA) check
ci: ## CI-friendly: lint (Biome) + Zola checks
$(BIOME) ci . && $(ZOLA) check
clean:
rm -rf public/

View File

@@ -1,27 +1,28 @@
# fr/website # Website
- My personal website https://www.filiprojek.cz
- Written in [Zola](https://getzola.org)
Personal website of **Filip Rojek** built with **[Zola](https://www.getzola.org/)** (Tera templates, SASS). ## To run development server
- `zola serve`
- Then it can be access at http://127.0.0.1:1111/
Live content: posts and projects. ## To Do
- [ ] Docker?
- [ ] redesign contact
- [ ] redesign about
- [ ] check about text content
- [ ] responsibility
--- # Projects
- nork
## Quick start - website
- debrepo
### Prerequisites - auto irrigation
- Zola (install from your distro or see https://www.getzola.org/documentation/getting-started/installation/) - auto awning close
- FofrTasks
### Develop - FofrMess
```bash - pkmples.cz
# run local dev server - deguapp?
zola serve - wpa_tui?
# default: http://127.0.0.1:1111 - dotfiles
````
### Build
```bash
# render to ./public
zola build
```

View File

@@ -1,41 +1,15 @@
{ {
"$schema": "https://biomejs.dev/schemas/2.2.2/schema.json", "$schema": "https://biomejs.dev/schemas/1.7.3/schema.json",
"vcs": {
"enabled": true,
"clientKind": "git",
"useIgnoreFile": true
},
"files": { "files": {
"includes": ["**", "!public", "!content", "!templates", "!static/img", "!**/*.min.js"] "ignore": [".vscode/", "node_modules/", "public/"]
}, },
"formatter": { "organizeImports": {
"enabled": true "enabled": true
}, },
"linter": { "linter": {
"enabled": true, "enabled": false,
"rules": { "rules": {
"recommended": true "recommended": true
} }
},
"javascript": {
"formatter": {
"lineWidth": 100,
"quoteStyle": "double",
"jsxQuoteStyle": "double",
"trailingCommas": "all",
"semicolons": "always"
}
},
"json": {
"formatter": {
"lineWidth": 100
}
},
"css": {
"formatter": {
"enabled": true,
"lineWidth": 100,
"quoteStyle": "single"
}
} }
} }

View File

@@ -1,5 +1,5 @@
# The URL the site will be built for # The URL the site will be built for
base_url = "https://www.filiprojek.cz" base_url = "https://dev.filiprojek.cz"
title = "Filip Rojek" title = "Filip Rojek"
compile_sass = true compile_sass = true

View File

@@ -3,25 +3,25 @@ title = "About"
template = "about.html" template = "about.html"
+++ +++
I am an IT student at Charles University in Prague (Faculty of Education). ## About
I am student of IT at Charles University in Prague (Faculty of Education).
As a member of [Microlab](https://microlab.space), the university's hackerspace, I collaborate on various hardware and software projects. Additionally, I contribute to the open-source community as a package maintainer for [Void Linux](https://voidlinux.org). My programming journey began in high school, where I developed a passion for `Linux` and co-founded [Fofrweb](https://fofrweb.com). Together with a classmate, I created web applications using `Node.js` and `Vue.js`, all hosted on my own Linux server.
As a member of [Microlab](https://microlab.space), the university's hacker space, I engage with fellow tech enthusiasts. Additionally, I contribute to the open-source community as a package maintainer for [Void Linux](https://voidlinux.org).
## Work ## Work
I currently work as a Linux engineer. Most of my work involves Debian based systems - desktops (Raspberry Pi, Intel NUC) and servers.
Currently employed as a Linux DevOps engineer, focusing primarily on Debian-based systems across a variety of hardware platforms. I also create custom websites from time to time.
I also create custom websites from time to time.
## Projects ## Projects
Most of my projects are hosted on Gitea and GitHub:
Most of my projects are hosted on my private Gitea instance and GitHub: - Gitea: [git.filiprojek.cz](https://git.filiprojek.cz/fr)
- Gitea: [git.filiprojek.cz/fr](https://git.filiprojek.cz/fr)
- GitHub: [github.com/filiprojek](https://github.com/filiprojek) - GitHub: [github.com/filiprojek](https://github.com/filiprojek)
## Contact ## Contact
- <a href="mailto:&#102;&#105;&#108;&#105;&#112;&#064;&#102;&#105;&#108;&#105;&#112;&#114;&#111;&#106;&#101;&#107;&#046;&#099;&#122;">&#102;&#105;&#108;&#105;&#112;&#064;&#102;&#105;&#108;&#105;&#112;&#114;&#111;&#106;&#101;&#107;&#046;&#099;&#122;</a> - <a href="mailto:&#102;&#105;&#108;&#105;&#112;&#064;&#102;&#105;&#108;&#105;&#112;&#114;&#111;&#106;&#101;&#107;&#046;&#099;&#122;">&#102;&#105;&#108;&#105;&#112;&#064;&#102;&#105;&#108;&#105;&#112;&#114;&#111;&#106;&#101;&#107;&#046;&#099;&#122;</a>
- [@filiprojek](https://t.me/filiprojek) on Telegram - [@filiprojek](https://t.me/filiprojek) on Telegram
- PGP: [0x7E65EA58C6075F09](https://keys.openpgp.org/vks/v1/by-fingerprint/CA3D9BE28315B49164130CD97E65EA58C6075F09) - PGP: [0x7E65EA58C6075F09](https://keys.openpgp.org/vks/v1/by-fingerprint/CA3D9BE28315B49164130CD97E65EA58C6075F09)

View File

@@ -1,91 +0,0 @@
+++
title = "Unix pass and Android Password Store with YubiKey"
date = 2025-01-01
description = "Setting Up Unix pass with YubiKey and Android Password Store"
+++
Using a secure and versatile password manager is a must for managing your digital life, and [pass](https://www.passwordstore.org/), the Unix password manager, is a fantastic choice. If you store your GPG key on a YubiKey and use the [Android Password Store](https://github.com/android-password-store/Android-Password-Store) app with [OpenKeychain](https://github.com/open-keychain/open-keychain), this guide will help you set everything up while addressing a common compatibility issue with `throw-keyids` in `gpg.conf`.
## What Youll Need
- A YubiKey configured with your GPG key (see the excellent [YubiKey-Guide by drduh](https://github.com/drduh/YubiKey-Guide)).
- The [pass](https://www.passwordstore.org/) command-line utility.
- [OpenKeychain](https://github.com/open-keychain/open-keychain) installed on your Android device.
- The [Android Password Store](https://github.com/android-password-store/Android-Password-Store) app.
## Configuring `pass` with a YubiKey-Stored GPG Key
1. **Set up your YubiKey and GPG key**
- Follow the steps in [drduhs YubiKey guide](https://github.com/drduh/YubiKey-Guide) to create and configure your GPG key on your YubiKey.
2. **Install `pass`**
- Install the `pass` utility on your Linux system. Most distributions have it in their package repositories:
```bash
apt install pass # For Debian/Ubuntu-based distros
xbps-install -S pass # For Void Linux
```
3. **Initialize `pass` with your GPG key**
- Run the following command to initialize the `.password-store` directory:
```bash
pass init <KEYID>
```
- Replace `<KEYID>` with your GPG key ID stored on the YubiKey.
4. **Sync passwords to your Android device**
- Clone your `.password-store` repository to your Android device and set up the `Password Store` app with `OpenKeychain`.
## The `throw-keyids` Issue
While working through this issue, I found a helpful discussion in [GitHub issue #173](https://github.com/android-password-store/Android-Password-Store/issues/173) for the Android Password Store repository. This thread provided insights that clarified the root cause of the problem and its resolution.
During setup, you might encounter an error in the Android Password Store app. OpenKeychain could report that the `.gpg` files are encrypted for a different key, even if they are not. This issue arises due to the `throw-keyids` option in `~/.gnupg/gpg.conf`.
### What Does `throw-keyids` Do?
The `throw-keyids` option in `gpg.conf` hides the recipients key ID during encryption. While this enhances privacy by preventing others from identifying the intended recipient(s), it can cause issues with OpenKeychain. OpenKeychain relies on visible key IDs to identify the correct decryption key, and without them, it assumes the files were encrypted for an unknown key.
### Fixing the Issue
To resolve this, you need to disable `throw-keyids` and re-encrypt your password store.
1. **Comment Out `throw-keyids` in `gpg.conf`**
- Open `~/.gnupg/gpg.conf` in your favorite text editor and comment out the line:
```
# throw-keyids
```
2. **Re-encrypt Your Password Store**
- Run the following command to re-encrypt all passwords with the new GPG options:
```bash
PASSWORD_STORE_GPG_OPTS="--no-throw-keyids" pass init <KEYID>
```
- Replace `<KEYID>` with your GPG key ID.
3. **Optional: Update Your Environment**
- To ensure `--no-throw-keyids` is always used, add the following line to your `~/.bashrc`:
```bash
export PASSWORD_STORE_GPG_OPTS='--no-throw-keyids' # Fix for OpenKeychain
```
- While this step is not strictly necessary (since the change in `gpg.conf` resolves the issue), it can serve as a safeguard.
4. **Sync the Updated Password Store**
- Push the updated `.password-store` to your remote repository and pull it on your Android device.
## Conclusion
With these steps, you can seamlessly use `pass` with a YubiKey and the Android Password Store app. The issue with `throw-keyids` is a minor hurdle that can be resolved by adjusting your `gpg.conf` and re-encrypting your password store. Disabling `throw-keyids` makes your key IDs visible, which slightly reduces privacy but is necessary for compatibility with OpenKeychain.
For further details on `pass`, GPG, or YubiKey, refer to their respective documentation. A secure password manager setup like this ensures your sensitive information stays safe across devices.
# References
- [Standard unix password manager](https://www.passwordstore.org/)
- [drduh's YubiKey Guide](https://github.com/drduh/YubiKey-Guide)
- [Android Password Store issue](https://github.com/android-password-store/Android-Password-Store/issues/173#issuecomment-453686599)

View File

@@ -1,141 +0,0 @@
+++
title = "Friendship ended with dwm, now River is my best friend"
date = 2025-10-21
description = "Moving from X11 with dwm to River on Wayland"
+++
After years with dwm on X11, I started hitting the limits of Xorg — especially screen tearing, smoothness, and missing Wayland-only features. I decided it was time to switch.
## Weapon of choice - River
I wanted an experience as close as possible to my existing X11/dwm/dwmblocks setup. Before i jumped into `river`, I looked at `dwl`, `sway`, and `Qtile`.
`dwl` sounded like the best choice for me since it aims to replicate dwm on Wayland. But development is slow, many protocols are still missing, and adding them takes time.
Sway wasn't bad, but it's closer to i3 than dwm, so not ideal for me.
Qtile looked good, but I didn't like configuring it in Python.
Then my friend [Emil](https://em.0x45.cz/) told me about his `river` setup. He was happy with it, so I gave it a shot.
What I really like about river is that I can configure it on the fly. The whole configuration is a single Bash script that sends commands to river live - no recompiling or restarting required.
As a layout manager I chose [Filtile](https://github.com/pkulak/filtile) as it's very similar to dwm behavior.
## Bar dwmblocks => waybar
As an alternative to `dwmblock`, I found Waybar to be the best fit for me.
It has plenty of modules for displaying almost anything on my bar, including my IP address, speaker/headphones state and battery status.
Besides using built-in modules, it's also possible to create custom ones using scripts. I've made my own module for displaying speaker/headphones volume with possibility to mute or change the default audio output on mouse click.
- `~/.config/waybar/config.jsonc`
```jsonc
...
"custom/audio": {
"exec": "~/.local/bin/waybar_audio.sh",
"return-type": "json",
"format": "{icon} {text}",
"format-icons": {
"speaker": ["", "", " "],
"speaker-muted": "󰖁",
"headphones": "󰋋",
"headphones-muted": "󰟎"
},
"interval": 2,
"on-click": "pamixer --toggle-mute",
"on-click-right": "~/.local/bin/toggle_audio",
"on-scroll-up": "pamixer --increase 5",
"on-scroll-down": "pamixer --decrease 5"
},
...
```
Where `waybar_audio.sh` and `toggle_audio` are my custom Bash scripts both available in my [dotfiles repository](https://git.filiprojek.cz/fr/dotfiles/src/branch/master/.local/bin).
## Application starter dmenu => Wmenu
I found Wmenu to be the most similar app launcher to dmenu and I don't like changes, so I picked it.
I was able to customize it to my liking - vertical list of apps.
The only thing that didn't work and I missed that feature so much was fuzzy search. Wmenu doesn't support it and there was no patch available. So I've decided to create my own version of wmenu with fuzzy search support with help of chatgpt codex :D. As much as I hate AI, Codex was actually able to modify that C code in just single prompt. My modified version of Wmenu is available in [this github repository](https://github.com/filiprojek/wmenu).
## passmenu integration to wmenu
For my password manager GUI I like to use passmenu - an dmenu script that helps me pick my password anywhere I am. But there was a problem. Passmenu was written only for dmenu. That's where chatgpt helped me again and together we created [this rewrite of passmenu](https://github.com/filiprojek/passmenu-wmenu) for Wmenu.
Passmenu is an excellent example of where I use the fuzzy search feature the most.
## Terminal alacritty => foot
Since Alacritty sucks at displaying images inside the terminal, I moved to foot as an alternative. It supports displaying images natively.
There was an issue with spawning new terminal inside the current working directory. I was used to Alacritty's <CTRL+Shift+Enter> shortcut. I fixed that with the following addition to my `.bashrc`:
```bash
osc7_cwd() {
local strlen=${#PWD}
local encoded=""
local pos c o
for (( pos=0; pos<strlen; pos++ )); do
c=${PWD:$pos:1}
case "$c" in
[-/:_.!\'\(\)~[:alnum:]] ) o="${c}" ;;
* ) printf -v o '%%%02X' "'${c}" ;;
esac
encoded+="${o}"
done
printf '\e]7;file://%s%s\e\\' "${HOSTNAME}" "${encoded}"
}
PROMPT_COMMAND=${PROMPT_COMMAND:+${PROMPT_COMMAND%;}; }osc7_cwd
```
And this keybind in `foot.ini`:
```ini
[key-bindings]
spawn-terminal=Control+Shift+Return
```
## Screenshare
Once I had my setup ready, one of the first issues after using it for some time was screen sharing. I dug into the issue and found a solution.
I had to add this to my River init file:
```bash
# Fix screen share
export XDG_CURRENT_DESKTOP=river
export XDG_SESSION_TYPE=wayland
## Start portals
dbus-update-activation-environment WAYLAND_DISPLAY XDG_CURRENT_DESKTOP
xdg-desktop-portal-wlr &
xdg-desktop-portal &
```
## Screenshots
On my X.org setup I was using screenshots with `shotgun` and `slop` based on my friend's tutorial: [Taking screenshots with shotgun and slop](https://em.0x45.cz/posts/taking-screenshots-with-shotgun-and-slop/). Fortunately he already wrote a guide for wayland alternative: [Taking screenshots on Wayland with Grim and Slurp](https://em.0x45.cz/posts/taking-screenshots-on-wayland-with-grim-and-slurp/).
But I had issues with the combination of `grim` and `slurp`. While pasting an image from clipboard to telegram, it pasted raw PNG data instead of a file. This was the fix:
```bash
riverctl map normal None Print spawn 'file="/home/$USER/Pictures/Screenshots/$(date +%F_%T).png"; grim -g "$(slurp -d)" "$file" && wl-copy --type text/uri-list "file://$file"'
```
## Other alternatives
This is a list of other software that I used on X.org and their alternatives on Wayland:
- `xclip` => `wl-copy`
- `ranger` => `yazi`
- `slock` => `waylock`
## Final thoughts
After a few weeks with River, I dont miss Xorg much. The setup feels lighter, screenshots and screen sharing work fine now, and I can still keep my DWM-like workflow.
There's just one thing I didn't get working and that is the indication of how many windows are open in monocle layout. Dwm used `[X]` where `X` was the number of open windows on that tag.
River feels more responsive overall, and I havent run into any crashes so far.
![My current river setup](/public/river_foot_waybar_setup.png)
## References
- [River - dynamic tiling Wayland compositor](https://codeberg.org/river/river-classic)
- [Filtile](https://github.com/pkulak/filtile)
- [Waybar](https://github.com/Alexays/Waybar)
- [Wmenu](https://codeberg.org/adnano/wmenu)
- [My fork of Wmenu with Fuzzy search support](https://github.com/filiprojek/wmenu)
- [Passmenu for wmenu](https://github.com/filiprojek/passmenu-wmenu)
- [Foot - Wayland terminal emulator](https://codeberg.org/dnkl/foot)

View File

@@ -1,39 +1,18 @@
+++ +++
title = "Debrepo" title = "Debrepo"
date = 2023-05-01 date = 2023-05-01
description = "Lightweight tool to create and manage Debian APT repositories" description = "A Debian repository management tool"
[extra] [extra]
state = "stable" state = "stable"
+++ +++
**Debrepo** is a lightweight tool for creating and managing Debian repositories for `*.deb` packages — a simple alternative to heavier tools like `reprepro` or `aptly`. # Debrepo
A Debian repository management tool.
#### **Key Features:** ## About
* **Init repository structure** (`debrepo init`) `Debrepo` is a software tool designed for creating and managing Debian repositories for `*.deb` packages, providing a lightweight and user-friendly alternative to more complex tools like `reprepo` or `aptly`. While these alternatives may offer more advanced features, Debrepo focuses on providing essential functionality and ease of use for repository management, allowing users to easily add, remove, and update packages within their repositories. With Debrepo, users can efficiently manage their Debian repositories without the unnecessary complexity of more advanced tools.
* **Add / delete packages** (`debrepo add`, `debrepo del`)
* **List packages** (`debrepo list`)
* **Built-in static serving** for quick testing (`debrepo serve`)
* **Minimal deps:** `sh`, `dpkg`, `gpg`, `python3`
#### **Quick usage** ## Links
```bash - [Git](https://git.filiprojek.cz/fr/debrepo)
# create repo structure
debrepo init /path/to/repo
# add a package
debrepo add ./build/foo_1.0_amd64.deb
# list & remove
debrepo list
debrepo del foo_1.0_amd64
# serve locally (for testing)
debrepo serve
````
Find the source here:
* Primary (Gitea): [https://git.filiprojek.cz/fr/debrepo](https://git.filiprojek.cz/fr/debrepo)
* GitHub (mirror): [https://github.com/filiprojek/debrepo](https://github.com/filiprojek/debrepo)

View File

@@ -1,24 +1,22 @@
+++ +++
title = "WALauncher" title = "WALauncher"
date = 2024-12-15 date = 2024-12-15
description = "A lightweight launcher for your web apps, an alternative to Muximux" description = "A lightweight launcher for your web apps, an alternative to Muximux "
[extra] [extra]
state = "done" state = "done"
+++ +++
**WALauncher** is a lightweight, web-based application launcher created as a modern alternative to [Muximux](https://github.com/mescon/Muximux). It is designed for effectively managing web applications such as Servarr, yet it offers extensive customization options suitable for various web-based services. The **WALauncher** project is a lightweight, web-based application launcher designed as a modern and streamlined alternative to [Muximux](https://github.com/mescon/Muximux). Its perfect for managing web applications like Servarr apps but is highly customizable to support any web-based services.
WALauncher enables users to organize their web services into a user-friendly dashboard, making it ideal for home servers or personal projects. WALauncher provides a sleek, user-friendly interface for consolidating your web services into a single, accessible dashboard, making it an efficient tool for home servers or personal projects.
#### **Key Features:** #### **Key Features**
- **Minimalistic Design:** Intuitive layout for easy access to all your web apps.
* **Minimalistic Design:** Intuitive layout for easy access to all your web apps. - **Docker Support:** Deploy effortlessly using the provided Docker setup for consistent and reliable hosting.
* **Docker Support:** Deploy effortlessly using the provided Docker setup for consistent and reliable hosting. - **Customizable:** Configure apps, icons, titles, and additional options to fit your preferences.
* **Customizable:** Configure apps, icons, titles, and additional options to fit your preferences. - **Open Source:** Contribute to or modify the project to suit your needs.
* **Open Source:** Contribute to or modify the project to suit your needs.
WALauncher combines simplicity and functionality for managing your web services with minimal overhead. Its a solution you can easily deploy and adapt to your workflow. WALauncher combines simplicity and functionality for managing your web services with minimal overhead. Its a solution you can easily deploy and adapt to your workflow.
Visit the [GitHub](https://github.com/filiprojek/walauncher) repository for additional information and screenshots. Visit the [GitHub](https://github.com/filiprojek/walauncher) repository for more details, screenshots, and support. Start managing your web apps with ease!

View File

@@ -7,40 +7,30 @@ timestamp=$(date +%s)
# Define an array of folders to skip # Define an array of folders to skip
skip_folders=("img" "svg" "fonts") skip_folders=("img" "svg" "fonts")
# Function to check if a path is within a skipped folder
is_skipped_folder() {
local path=$1
for skip in "${skip_folders[@]}"; do
if [[ "$path" == */$skip/* ]]; then
return 0
fi
done
return 1
}
# Function to add timestamp to CSS files and update HTML imports # Function to add timestamp to CSS files and update HTML imports
update_css_references() { update_css_references() {
find "$public_dir" -type f -name "*$css_extension" | while read -r css_file; do # Find all CSS files in the root of the public directory
if is_skipped_folder "$css_file"; then for css_file in "$public_dir"/*$css_extension; do
continue if [[ -f "$css_file" ]]; then
base_name=$(basename "$css_file" "$css_extension")
new_name="${base_name}-${timestamp}${css_extension}"
# Rename the CSS file
mv "$css_file" "$public_dir/$new_name"
echo "Renamed: $css_file -> $new_name"
# Update all HTML files in the root and 'archiv' folder
for html_file in "$public_dir"/*.html "$public_dir/archiv/"*.html; do
if [[ -f "$html_file" ]]; then
sed -i "s|$base_name$css_extension|$new_name|g" "$html_file"
echo "Updated references in: $html_file"
fi
done
fi fi
base_dir=$(dirname "$css_file")
base_name=$(basename "$css_file" "$css_extension")
new_name="${base_name}-${timestamp}${css_extension}"
new_path="${base_dir}/${new_name}"
# Rename the CSS file
mv "$css_file" "$new_path"
echo "Renamed: $css_file -> $new_path"
# Update all HTML files under public recursively
find "$public_dir" -type f -name "*.html" | while read -r html_file; do
sed -i "s|$base_name$css_extension|$new_name|g" "$html_file"
echo "Updated references in: $html_file"
done
done done
} }
# Add timestamp to CSS files and update HTML references (including archiv/index.html)
update_css_references update_css_references

View File

@@ -1,20 +1,9 @@
.about { .about {
h1 {
font-size: 2rem;
margin-bottom: 2rem;
}
h2 { h2 {
margin-top: 1rem; margin-top: 1rem;
margin-bottom: .5rem; margin-bottom: .5rem;
} }
h3, h4, h5, h6, p {
h3,
h4,
h5,
h6,
p {
margin-top: .5rem; margin-top: .5rem;
margin-bottom: .5rem; margin-bottom: .5rem;
} }
@@ -22,6 +11,5 @@
p { p {
text-align: left; text-align: left;
} }
margin-bottom: 3rem; // space for footer
} }

View File

@@ -24,30 +24,6 @@
display: none; display: none;
} }
} }
.latest-projects-posts {
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
gap: 1rem;
margin-top: 5rem;
margin-bottom: 2rem;
.project {
display: flex;
flex-direction: column;
margin: 1rem 0;
width: 100%;
max-width: 40%;
gap: 1rem;
.title {
font-size: 1.2rem;
}
.description {
font-size: 1rem;
}
}
}
@media (max-width: 600px) { @media (max-width: 600px) {
#pgp { #pgp {
display: none; display: none;
@@ -55,9 +31,5 @@
#pgpmobile { #pgpmobile {
display: inline-block; display: inline-block;
} }
.latest-projects-posts .project {
margin: 1rem 5%;
max-width: 90%;
}
} }

View File

@@ -43,10 +43,6 @@ code {
p { p {
text-align: left; text-align: left;
} }
img {
max-width: 100%;
}
} }
.link-back { .link-back {
@@ -55,7 +51,6 @@ code {
.copy-code-wrapper { .copy-code-wrapper {
position: relative; position: relative;
margin-block-start: 1em; // Fixes wrong margin when code block is inside listed item
} }
.copy-code { .copy-code {
@@ -71,7 +66,13 @@ code {
@media (max-width: 768px) { @media (max-width: 768px) {
.project-wrapper { .project-wrapper {
max-width: 100%; max-width: 100%;
margin: 0rem 1rem; padding: 1rem;
}
}
@media (max-width: 480px) {
.project-wrapper {
padding: 5px;
} }
} }

View File

@@ -7,7 +7,7 @@
body { body {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
min-height: 100dvh; min-height: 100vmax;
font-family: 'Source Code Pro', monospace; font-family: 'Source Code Pro', monospace;
background: var(--background); background: var(--background);
color: var(--color); color: var(--color);
@@ -79,8 +79,7 @@ footer {
align-items: center; align-items: center;
align-self: flex-end; align-self: flex-end;
margin-top: auto; margin-top: auto;
margin-bottom: max(2rem, env(safe-area-inset-bottom)); /* Account for safe area */ margin-bottom: 2rem;
} }
.hamburger { .hamburger {

View File

@@ -1,28 +1,30 @@
const codes = document.querySelectorAll("pre"); let codes = document.querySelectorAll("pre")
codes.forEach((code) => { codes.forEach(code => {
const elWrapper = document.createElement("div"); const elWrapper = document.createElement("div")
elWrapper.classList.add("copy-code-wrapper"); elWrapper.classList.add("copy-code-wrapper")
const el = document.createElement("span");
el.textContent = "Copy";
el.classList.add("copy-code");
elWrapper.appendChild(el); const el = document.createElement("span")
el.textContent = "Copy"
el.classList.add("copy-code")
code.parentNode.insertBefore(elWrapper, code); elWrapper.appendChild(el)
let textContent = ""; code.parentNode.insertBefore(elWrapper, code)
code.childNodes.forEach((child) => {
textContent += child.textContent; let textContent = ""
}); code.childNodes.forEach(child => {
textContent += child.textContent;
})
elWrapper.addEventListener("click", (e) => {
e.preventDefault()
navigator.clipboard.writeText(textContent)
el.textContent = "Copied!"
setTimeout(() => {
el.textContent = "Copy"
}, 5000);
})
})
elWrapper.addEventListener("click", (e) => {
e.preventDefault();
navigator.clipboard.writeText(textContent);
el.textContent = "Copied!";
setTimeout(() => {
el.textContent = "Copy";
}, 5000);
});
});

107
static/js/console.js Normal file
View File

@@ -0,0 +1,107 @@
const c = document.querySelector(".console")
const ps1 = "[fr@website ~]$ "
const motd = "Welcome to my website!<br>You can use `help` for more informations :)"
let line = "";
function exec(command) {
switch (command[0]) {
case "help":
line = "help<br>author<br>contact<br>clear<br>echo"
break;
case "author":
line = "Filip Rojek, 2023"
break
case "contact":
line = "Filip Rojek &lt<a href='mailto: &#102;&#105;&#108;&#105;&#112;&#064;&#102;&#105;&#108;&#105;&#112;&#114;&#111;&#106;&#101;&#107;&#046;&#099;&#122;'>&#102;&#105;&#108;&#105;&#112;&#064;&#102;&#105;&#108;&#105;&#112;&#114;&#111;&#106;&#101;&#107;&#046;&#099;&#122;</a>&gt<br>web: <a href='https://filiprojek.cz' target='_blank'>www.filiprojek.cz</a><br>telegram: <a href='https://t.me/filiprojek' target='_blank'>@filiprojek</a>"
break
case "clear":
write("000ctrll")
return false
case "echo":
line = ""
command.forEach((cmd, i) => {
if (i === 0) return
line += cmd + " "
});
line = line.substring(0, line.length - 1) // remove last space
break
default:
line = "frsh: " + command[0] + ": command not found"
break;
}
return line
}
function write(key, payload) {
switch(key) {
case "Enter":
command = c.lastChild.textContent.replace(ps1, "")
command = command.split(" ");
let out = exec(command)
if(out !== false) {
line = document.createElement("p")
line.innerHTML += out
line.innerHTML += "<br>"
c.appendChild(line)
line = document.createElement("p")
line.innerHTML += ps1
c.appendChild(line)
}
command = ""
break
case "000ctrll":
c.innerHTML = ""
if(payload == motd) c.innerHTML = motd
line = document.createElement("p")
line.innerHTML += ps1
c.appendChild(line)
break
case "000backspace":
if(c.lastChild.textContent.slice(0, -1) !== ps1.slice(0, -1)) {
c.lastChild.innerHTML = c.lastChild.textContent.slice(0, -1)
}
break
default:
c.lastChild.innerHTML += key
}
}
function customCtrlShortcuts(plusKey) {
document.addEventListener("keydown", e => {
if(e.ctrlKey && e.key == plusKey) {
e.preventDefault()
write("000ctrl"+plusKey)
}
})
}
// On load init the terminal
window.addEventListener("load", () => {
write("000ctrll", motd)
if (navigator.userAgent.toLowerCase().includes("mobile")) {
const mi = document.querySelector(".mobile-input")
mi.style="opacity: 0; width: 0; height: 0"
c.addEventListener("click", e => {
mi.focus()
})
}
})
// Capture the keypress
window.addEventListener("keypress", e => {
e.preventDefault()
write(e.key)
})
window.addEventListener("keydown", e => {
if(e.key == "Backspace") {
e.preventDefault()
write("000backspace")
}
})
// Register custom ctrl shortcuts
customCtrlShortcuts("l") // ctrl + l
customCtrlShortcuts("c") // ctrl + c

View File

@@ -1,24 +1,26 @@
const burger = document.querySelector(".hamburger"); const burger = document.querySelector(".hamburger")
const links = document.querySelector(".links"); const links = document.querySelector(".links")
const body = document.querySelector("body"); const body = document.querySelector("body")
const main = document.querySelector("main"); const main = document.querySelector("main")
let shown = false; let shown = false
burger.addEventListener("click", (e) => { burger.addEventListener("click", (e) => {
e.preventDefault(); e.preventDefault()
if (!shown) {
links.style.display = "flex"
body.classList.add("disable-scroll")
burger.textContent = "x"
main.style.visibility = "hidden"
} else {
links.style.display = "none"
body.classList.remove("disable-scroll")
burger.textContent = "☰"
main.style.visibility = "visible"
}
shown = !shown
})
if (!shown) {
links.style.display = "flex";
body.classList.add("disable-scroll");
burger.textContent = "x";
main.style.visibility = "hidden";
} else {
links.style.display = "none";
body.classList.remove("disable-scroll");
burger.textContent = "☰";
main.style.visibility = "visible";
}
shown = !shown;
});

Binary file not shown.

Before

Width:  |  Height:  |  Size: 379 KiB

View File

@@ -6,7 +6,6 @@
{% block content %} {% block content %}
<section class="about content"> <section class="about content">
<h1>{{ page.title }}</h1> {{ page.content | safe }}
{{ page.content | safe }}
</section> </section>
{% endblock content %} {% endblock content %}

View File

@@ -28,7 +28,6 @@
<script defer src="/js/mobile-navbar.js"></script> <script defer src="/js/mobile-navbar.js"></script>
{% block styles %} {% block styles %}
{% endblock styles %} {% endblock styles %}
<script defer data-domain="filiprojek.cz" src="https://analytics.fofrweb.com/js/script.js"></script>
</head> </head>
<body> <body>
<header> <header>
@@ -61,7 +60,6 @@
{% endblock content %} {% endblock content %}
</main> </main>
<footer> <footer>
<p>Built using <a href="https://getzola.org" target="_blank">Zola SSG</a></p>
<p>Build time: {{ now() | date(format="%Y-%m-%d %H:%M") }}, <p>Build time: {{ now() | date(format="%Y-%m-%d %H:%M") }},
{% if config.extra.git %} {% if config.extra.git %}
<a href="{{ config.extra.git }}" target="_blank">Source</a> <a href="{{ config.extra.git }}" target="_blank">Source</a>

View File

@@ -5,7 +5,7 @@
<section> <section>
<p>Filip Rojek &lt&#102;&#105;&#108;&#105;&#112;&#064;&#102;&#105;&#108;&#105;&#112;&#114;&#111;&#106;&#101;&#107;&#046;&#099;&#122;&gt</p> <p>Filip Rojek &lt&#102;&#105;&#108;&#105;&#112;&#064;&#102;&#105;&#108;&#105;&#112;&#114;&#111;&#106;&#101;&#107;&#046;&#099;&#122;&gt</p>
<br> <br>
<p>Linux sysadmin, software engineer <a href="https://www.fofrweb.com/" target="_blank">@fofrweb</a>,<br> GNU/Linux <a href="http://voidlinux.org" target="_blank">Void</a> contributor and student at Charles University in Prague<span class="underscore">_</span><p> <p>Linux sysadmin, backend node.js & php developer <a href="https://www.fofrweb.com/" target="_blank">@fofrweb</a>,<br> GNU/Linux <a href="http://voidlinux.org" target="_blank">Void</a> user, student and coffee enthusiast<span class="underscore">_</span><p>
<br> <br>
<p>PGP: <a href="https://keys.openpgp.org/vks/v1/by-fingerprint/CA3D9BE28315B49164130CD97E65EA58C6075F09" target="_blank">0x7E65EA58C6075F09</a></p> <p>PGP: <a href="https://keys.openpgp.org/vks/v1/by-fingerprint/CA3D9BE28315B49164130CD97E65EA58C6075F09" target="_blank">0x7E65EA58C6075F09</a></p>
<br> <br>
@@ -22,38 +22,5 @@
</script> </script>
</section> </section>
{# how many items to show #}
{% set n = 6 %}
{# fetch sections #}
{% set posts = get_section(path="posts/_index.md") %}
{% set projects = get_section(path="projects/_index.md") %}
{# merge, sort by date (desc), take first n #}
{% set latest = posts.pages
| concat(with=projects.pages)
| sort(attribute="date")
| reverse
| slice(end=n)
%}
<section class="latest-projects-posts">
<h2>Latest projects & posts</h2>
{% for page in latest %}
<div class="project">
<a class="title" href="{{ page.permalink }}">{{ page.title }}</a>
<p class="description">
{% if page.description %}{{ page.description }}{% else %}&hellip;{% endif %}
</p>
<hr>
<p>
{{ page.date }}
{% if page.path is starting_with("posts/") %} · Post
{% elif page.path is starting_with("projects/") %} · Project
{% endif %}
</p>
</div>
{% endfor %}
</section>
{% endblock content %} {% endblock content %}

View File

@@ -20,7 +20,7 @@
{% endif %} {% endif %}
</p> </p>
<hr> <hr>
<p>{{ project.date }}</p> <p>{{ project.date }} | {{ project.extra.state}}</p>
</div> </div>
{% endfor %} {% endfor %}
</section> </section>