Advertisement · 728 × 90
#
Hashtag
#ExtraCurricular
Advertisement · 728 × 90
Preview
Unified Theming on a Wayland Desktop – In 220 Lines of Bash ### Article summary * The Problem: N Apps, N Formats, Zero Coordination * The Architecture: Convention Over Configuration * The Apply Sequence * The Hard Parts * The Rofi GUI * Adding a New Theme * Design Decisions and Trade-offs * What's Next * See it in action During the COVID-19 pandemic, I like many found myself with a lot of free time. So like many others, I deciding to spend way too much time on my computer. This led to ultimately running into frustration with the lack of a unified theme system. with MacOS, which not longer ran well the ancient 2013 Macbook Pro I was using at the time. I saw how others online were able to have complete control over their desktop environment. So I decided to switch to Linux for my daily driver and try my hand at customizing my desktop environment. Fast forward several years later, and I’ve gotten pretty decent at it. Here’show I built a single command that switches the theme across my entire Hyprland desktop: terminal, status bar, launcher, notifications, wallpaper, tmux, and every running Neovim instance. ## The Problem: N Apps, N Formats, Zero Coordination On macOS, you flip one toggle and the whole OS goes dark. On Windows, same story. On a tiling Wayland compositor like Hyprland, you’re on your own. My daily desktop is Hyprland on Arch Linux. The tools I use every day (Alacritty, Waybar, Rofi, SwayNC, Tmux, Neovim) each have their own config format, their own color syntax, and their own reload mechanism. There is no unified theme API. No dbus signal. No XSettings daemon. Nothing that says “hey, the user wants Catppuccin now.” Here’s what “switching themes” actually means: App | Config Format | Reload Method ---|---|--- Alacritty | TOML | Watches config file Waybar | CSS | `SIGUSR2` Rofi | rasi | Next invocation SwayNC | CSS (GTK) | `swaync-client -rs` Wallpaper | Image file | `swww img` Tmux | tmux.conf | `tmux source-file` Neovim | Plain text + Lua RPC | `nvr` remote commands Seven apps. Five config formats. Five different reload mechanisms. Tools like `pywal` generate color palettes from wallpapers, but I wantedcurated themes, hand-picked color files from upstream projects, applied consistently everywhere, with one command. So I, with a little help from Claude, wrote a script that can apply a theme to my entire desktop. ## The Architecture: Convention Over Configuration The whole system rests on one idea: **a theme is a directory with known filenames**. That’s the entire contract. No manifest. No JSON registry. No config file that lists themes. Drop a folder in, it works. themes/ alacritty-base.toml # shared structure (font, window, keybindings) .current-theme # state: one line, theme name scripts/ theme-switcher # the CLI rofi-themeswitcher # GUI picker themes/ CatppuccinMocha/ alacritty-colors.toml waybar.css rofi.rasi swaync.css tmux.conf nvim.txt wallpaper.png # optional Dracula/ Nord/ ... # 14 themes total Theme discovery is a directory scan: for theme_dir in "$THEMES_DIR"/*/; do theme_name=$(basename "$theme_dir") done No registration step or adding your theme to `themes.json`. If the directory exists and has the right files, it’s a theme. Currently I maintain 14, roughly 7 dark/light pairs plus a couple of standalones: * CatppuccinMocha / CatppuccinLatte * Dracula * Everforest / EverforestLight * Gruvbox / GruvboxLight * Nord / NordLight * RosePine / RosePineDawn * SolarizedLight * TokyoNight / TokyoNightDay ### The Alacritty Split One design choice worth calling out: Alacritty’s config is split into two files. The base config holds everything structural (font, window opacity, padding, keybindings): # alacritty-base.toml (shared across all themes) [general] live_config_reload = true [window] decorations = "None" opacity = 0.8 padding = { x = 16, y = 16 } [font] normal = { family = "VictorMono Nerd Font", style = "Regular" } size = 14.0 Each theme provides only the color definitions: # CatppuccinMocha/alacritty-colors.toml [colors.primary] background = "#1e1e2e" foreground = "#cdd6f4" [colors.normal] black = "#45475a" red = "#f38ba8" green = "#a6e3a1" # ... At apply time, the script concatenates them. The structure never changes; colors swap cleanly. This also means I can edit font or opacity in one place and it applies to every theme. ## The Apply Sequence Running `theme-switcher apply CatppuccinMocha` triggers a sequential pipeline. Each step checks for the relevant file, applies it, and moves on. If an app isn’t installed or isn’t running, the step is skipped. The script never fails because something is missing. $ theme-switcher apply CatppuccinMocha Applying theme: CatppuccinMocha ✓ Alacritty theme applied (live reload) ✓ Waybar style updated ✓ Waybar reloaded ✓ Rofi colors updated ✓ Swaync style updated ✓ Swaync reloaded ✓ Wallpaper set ✓ Tmux theme updated ✓ Tmux reloaded ✓ Neovim colorscheme updated ✓ Neovim instances updated Theme 'CatppuccinMocha' applied successfully! The whole thing takes under a second. Let’s look at the interesting parts. ## The Hard Parts ### Atomic Writes for Alacritty Alacritty watches its config file and reloads on change. That’s great, until you realize that writing a file isn’t atomic. If Alacritty reads the file mid-write, it gets a partial config and either errors out or briefly flashes garbage. The fix is the oldest trick in Unix: tmpfile=$(mktemp "${ALACRITTY_CONFIG}.XXXXXX") cat "$ALACRITTY_BASE" "$theme_path/alacritty-colors.toml" > "$tmpfile" mv "$tmpfile" "$ALACRITTY_CONFIG" Write to a temp file in the same directory, then `mv`. On the same filesystem, `mv` is an atomic rename. Alacritty never sees a half-written file. Three lines, zero flicker. ### Neovim Is the Boss Fight Every other app follows the same pattern: copy a file, maybe send a signal. Neovim is different. Neovim colorschemes aren’t just color tables. They’re Lua plugins with setup functions, variant options, and background mode dependencies. The script reads a single line from `nvim.txt` (e.g., `catppuccin-mocha`), then uses nvr to push commands to every running Neovim instance. But different colorschemes need different setup: case "$colorscheme" in rose-pine-*) # Rose Pine needs Lua setup with variant extraction nvr -c "lua require('rose-pine').setup({ variant = '${colorscheme#rose-pine-}' })" nvr -c "colorscheme rose-pine" ;; catppuccin-mocha) # Catppuccin uses a flavour parameter nvr -c "lua require('catppuccin').setup({ flavour = 'mocha' })" nvr -c "colorscheme catppuccin" ;; gruvbox-light) # Light themes need background=light before the colorscheme nvr -c "set background=light" nvr -c "lua require('gruvbox').setup({ transparent_mode = true })" nvr -c "colorscheme gruvbox" ;; everforest|gruvbox|nord) # Dark variants need explicit background=dark nvr -c "set background=dark" nvr -c "colorscheme $colorscheme" ;; *) # Simple themes: just set the colorscheme nvr -c "colorscheme $colorscheme" ;; esac A few things to note here: * **Input validation.** The colorscheme name is passed to `nvr -c`, which executes Vim commands. A malicious `nvim.txt` could inject arbitrary commands. So the script validates the name against `^[a-zA-Z0-9_-]+$` before using it. * **Server discovery.** The script captures the server list once with `nvr --serverlist` and iterates over it, rather than calling `--serverlist` per command. This avoids race conditions where an instance starts or stops mid-apply. * **Graceful absence.** If `nvr` isn’t installed, the script writes the colorscheme file (so Neovim picks it up on next launch) and moves on. If no instances are running, it says so and continues. This is the part of the script I touch most often. Every time I add a theme with a non-trivial Neovim setup, the case statement grows. It’s the one place where the “convention over configuration” philosophy hits a wall. Neovim colorschemes simply aren’t uniform. ### Daemon Lifecycle: swww swwwis a wallpaper daemon for Wayland. You can’t set a wallpaper unless the daemon is running, and the daemon takes a moment to initialize. The script handles this with a polling loop: ensure_swww_daemon() { if ! pgrep -x swww-daemon &>/dev/null; then swww-daemon &>/dev/null & disown for i in $(seq 1 50); do swww query &>/dev/null && return 0 sleep 0.1 done echo " ! swww daemon failed to start" >&2 return 1 fi } Start the daemon, then poll `swww query` up to 50 times at 100ms intervals (5 second timeout). Once it responds, proceed. If it doesn’t come up, report the failure and skip the wallpaper. The code>disown detaches the daemon from the script’s process group so it survives after the script exits. This is really more of an edge case, because I launch the daemon automatically with an ‘exec’ in my `hyprland.conf`. ## The Rofi GUI The CLI is great for scripting, but day-to-day I use a Rofi picker bound to a hotkey. It’s a thin wrapper (about 50 lines) that builds a menu from the same theme directories, marks the current theme with a bullet, and calls `theme-switcher apply` with the selection: # Build the menu for theme_dir in "$THEMES_DIR"/*/; do theme_name=$(basename "$theme_dir") if [[ "$theme_name" == "$current" ]]; then echo "● $theme_name" else echo " $theme_name" fi done # Pipe to rofi, clean selection, apply selected=$(get_theme_list | rofi -dmenu -i -p "Theme") The picker inherits the current Rofi theme, so it always looks native to whatever theme you’re currently running. A nice side effect of the system theming itself. ## Adding a New Theme This is the part I’m most satisfied with: adding a theme is a five-minute task: 1. Create a directory: `themes/themes/MyTheme/` 2. Add 6 files: `alacritty-colors.toml`, `waybar.css`, code>rofi.rasi, `swaync.css`, `tmux.conf`, `nvim.txt` 3. Optionally drop in a `wallpaper.png` 4. Run `theme-switcher apply MyTheme` No build step. No compilation. No registration. The directory scan picks it up immediately. Most of the time I’m pulling color values from the upstream theme project’s official ports and adapting them to each config format. The Alacritty and Neovim files are usually available directly; Waybar and SwayNC CSS require more manual work. ## Design Decisions and Trade-offs **Why bash?** Because every tool in the pipeline is a CLI program. The script is orchestration glue: `cat`, `cp`, `mv`, `pkill`, `pgrep`. There’s no data transformation complex enough to justify Python or a compiled language. Bash is the right tool when the job is “run these 12 commands in order.” ## What’s Next The system works well for my daily use, but there are gaps I’d like to close: * **GTK theming.** GTK apps (Thunar, Firefox to some extent) still use their own theme. Integrating `gsettings` or `gtk-3.0/settings.ini` into the pipeline would close the biggest remaining visual inconsistency. * **Time-based switching.** A cron job or timer that switches to a light theme at sunrise and dark at sunset. The infrastructure supports it. It’s just `theme-switcher apply EverforestLight` in a script. * **Reducing the Neovim case statement.** The per-colorscheme branching is the one piece that doesn’t scale cleanly. I’m considering a small metadata file per theme (e.g., `nvim-setup.lua`) that the script could source directly, replacing the bash case logic with theme-local Lua. * * * ## See it in action The full source is in my dotfiles repo. The theme-switcher script is ~220 lines of bash. The Rofi wrapper is ~50. Together they give me a unified theme experience across my entire desktop with a single command or a hotkey. A composable Linux desktop gives you the freedom to choose every piece of your environment. The cost of that freedom is that nobody’s going to wire those pieces together for you. Sometimes the best tool for the job is a bash script that knows where all the config files live. Bryan Paronto Software Consultant & Developer at Atomic Object Chicago. Driven to deliver good software experiences by an insatiable thirst for knowledge, a deep love of creative problem-solving, and a desire to turn out quality work All Posts → ### Related Posts * Extracurricular Activities ## From Simple Circuits to Powerful Systems * Extracurricular Activities ## I Built a Pokémon Trainer AI With LangChain * Extracurricular Activities ## Automatically Log In to an Ubuntu Head

Unified Theming on a Wayland Desktop – In 220 Lines of Bash During the COVID-19 pandemic, I like many found myself with a lot of free time. So like many others, I deciding to spend way too much t...

#Extracurricular #Activities

Origin | Interest | Match

0 0 0 0
Post image

Our Year 9 Cookery Skills Club is off to a busy start as pupils begin a six‑week programme developing practical kitchen skills and confidence.

A great start to an exciting half term of cooking and learning.

#Opportunity #WHSCookery #ExtraCurricular #WeAreWHS

0 0 0 0
Post image

Our extra curricular clubs give pupils the chance to explore interests, build confidence, and enjoy learning beyond the classroom in a fun and supportive environment.

These our are lovely lower school students finding their Happy place :)

#ExtraCurricular #cookingclub #OaksPark

0 0 0 0
Post image

Extra-curricular clubs give our students amazing opportunities beyond the classroom.

Here’s our Drama Club showing off their brilliant work to their parents.
All smiles, confidence, and creativity.

Which club have you signed up for?

#OaksPark
#ExtraCurricular

0 0 0 0
Video

A familiar face on the pitch. Anthony Cupidore aka Coach Church from #TeachersRugbyClub—volunteers his time each year to coach our rugby #extracurricular. His commitment, experience, and love of the game continue to make a meaningful difference for our students. #SomersfieldAcademy

0 0 0 0
Post image Post image Post image Post image

Oriel Chess Club was super busy and super competitive tonight. Great to see so much concentration and enjoyment all in one place!! Thanks to Mr Sandom for running this every week! 💜♟️💜♟️💜 #OrielClubs #ExtraCurricular #CheckMate

0 0 0 0
Preview
Automatically Log In to an Ubuntu Head ### Article summary * The Problem * The Solution * Conclusion I have a piece of software I need running continuously on one of my Ubuntu virtual machines. Sadly, for some reason I cannot explain, that software requires a user be logged into the head. But my virtual machine barely has a head. And I certainly don’t want to be logged into it all the time. This post is about a workaround I found. ## The Problem This piece of software needs to be started manually after boot. Once it’s started, it’ll keep running as a daemon. Oddly, on that first startup, there needs to be an account logged into the head. If not, it’ll refuse to start. Even more oddly, you don’t even need to start it from the head. You simply need to have _something_ connected to the head, and then you can do the rest over ssh. I don’t get it either. But that’s what I have in front of me. The challenge is that I have this Ubuntu instance running as a virtual machine on my Proxmox host. There isn’t much of a head to be using! It technically does exist as a serial console, but no sane person is going to use it — sane people will use this virtual machine and software over ssh. Not exactly easy for me to get logged into the head. ## The Solution My uh… solution … is to have an account automatically log into the head after the system restarts. I can do that on my Ubuntu Noble virtual machine with a systemd unit. Run this command: `sudo systemctl edit [email protected]` and add this content into the editor that opens: [Service] ExecStart= ExecStart=-/sbin/agetty --autologin fletcher --keep-baud 115200,57600,38400,9600 - $TERM Type=idle (Fill in the appropriate user account after `--autologin` – in my case, that’s `fletcher`.) Then run these commands to ensure systemd is aware of the new unit: sudo systemctl daemon-reload sudo systemctl enable --now [email protected] sudo systemctl restart [email protected] Now reboot and watch the machine boot. You should see it automatically login when it’s done booting. ### The Obvious Security Problem This thing is logging in automatically, so be mindful about whether you really need or want this, and what the security impact could be. In my case, this is a virtual machine running in my private, internal cluster that no one else can access. It’ll be okay. ### Which tty? The above code assumes `ttys0` , since that is what the virtual machine’s serial display shows up as in Ubuntu Noble. Depending on your distribution and whether you’re using Proxmox or not, you may have a different tty. If so, adjust the tty in the filename and commands above. ## Conclusion Now that my account automatically logs into the head after reboot, this other piece of software is perfectly happy to let me start it, as needed, over SSH. Thanks to a couple of references out there for helping me figure out how to do this: * Simon Jones’s post about agetty and autologin. * A StackOverflow post about using ExecStart. Linuxsystemd Matt Fletcher Long term Grand Rapids software development consultant. All Posts → ### Related Posts * Extracurricular Activities ## Level Up Your Emoji Game: A Command-Line Shortcut for Making Custom Slack Emojis * Extracurricular Activities ## PottyMon: Keeping the Bathroom Monitor Tradition Alive * Extracurricular Activities ## An Ansible Role to Install my Proxmox Backup Client Scripts

Automatically Log In to an Ubuntu Head I have a piece of software I need running continuously on one of my Ubuntu virtual machines. Sadly, for some reason I cannot explain, that software requires a...

#Extracurricular #Activities #Linux #systemd

Origin | Interest | Match

0 0 0 0
Preview
Automatically Log In to an Ubuntu Head ### Article summary * The Problem * The Solution * Conclusion I have a piece of software I need running continuously on one of my Ubuntu virtual machines. Sadly, for some reason I cannot explain, that software requires a user be logged into the head. But my virtual machine barely has a head. And I certainly don’t want to be logged into it all the time. This post is about a workaround I found. ## The Problem This piece of software needs to be started manually after boot. Once it’s started, it’ll keep running as a daemon. Oddly, on that first startup, there needs to be an account logged into the head. If not, it’ll refuse to start. Even more oddly, you don’t even need to start it from the head. You simply need to have _something_ connected to the head, and then you can do the rest over ssh. I don’t get it either. But that’s what I have in front of me. The challenge is that I have this Ubuntu instance running as a virtual machine on my Proxmox host. There isn’t much of a head to be using! It technically does exist as a serial console, but no sane person is going to use it — sane people will use this virtual machine and software over ssh. Not exactly easy for me to get logged into the head. ## The Solution My uh… solution … is to have an account automatically log into the head after the system restarts. I can do that on my Ubuntu Noble virtual machine with a systemd unit. Run this command: `sudo systemctl edit [email protected]` and add this content into the editor that opens: [Service] ExecStart= ExecStart=-/sbin/agetty --autologin fletcher --keep-baud 115200,57600,38400,9600 - $TERM Type=idle (Fill in the appropriate user account after `--autologin` – in my case, that’s `fletcher`.) Then run these commands to ensure systemd is aware of the new unit: sudo systemctl daemon-reload sudo systemctl enable --now [email protected] sudo systemctl restart [email protected] Now reboot and watch the machine boot. You should see it automatically login when it’s done booting. ### The Obvious Security Problem This thing is logging in automatically, so be mindful about whether you really need or want this, and what the security impact could be. In my case, this is a virtual machine running in my private, internal cluster that no one else can access. It’ll be okay. ### Which tty? The above code assumes `ttys0` , since that is what the virtual machine’s serial display shows up as in Ubuntu Noble. Depending on your distribution and whether you’re using Proxmox or not, you may have a different tty. If so, adjust the tty in the filename and commands above. ## Conclusion Now that my account automatically logs into the head after reboot, this other piece of software is perfectly happy to let me start it, as needed, over SSH. Thanks to a couple of references out there for helping me figure out how to do this: * Simon Jones’s post about agetty and autologin. * A StackOverflow post about using ExecStart. Linuxsystemd Matt Fletcher Long term Grand Rapids software development consultant. All Posts → ### Related Posts * Extracurricular Activities ## Level Up Your Emoji Game: A Command-Line Shortcut for Making Custom Slack Emojis * Extracurricular Activities ## PottyMon: Keeping the Bathroom Monitor Tradition Alive * Extracurricular Activities ## An Ansible Role to Install my Proxmox Backup Client Scripts

Automatically Log In to an Ubuntu Head I have a piece of software I need running continuously on one of my Ubuntu virtual machines. Sadly, for some reason I cannot explain, that software requires a...

#Extracurricular #Activities #systemd #Linux

Origin | Interest | Match

0 0 0 0
Preview
5 doramas curtos para assistir antes do ano acabar Descubra uma lista de doramas curtos que você vai querer maratonar antes que o ano chegue ao fim
0 0 0 0
Post image

The Robotics Club is gearing up for an exciting competition this March! We’re looking for sponsors to help make this journey a success—please reach out if you’d like to support them.

#WHSRobotics #Commitment #Opportunity #ExtraCurricular

1 0 0 0
Preview
Robbin Hood (Lack of Afro Remix), by Extra Curricular from the album The Craig Charles Funk & Soul Club, Vol. 3


🇺🇦 #NowPlaying on #BBC6Music's #TheCraigCharlesFunkAndSoulShow

Extra Curricular:
🎵 Robbin Hood (Lack Of Afro Mix)

#6music #ExtraCurricular

▶️ 🪄 Automagic 🔊 show 📻 playlist on Spotify

▶️ Song/Cover on #Bandcamp:

1 0 0 0
Preview
5 doramas com boas atuações para você assistir e se impressionar Confira alguns doramas que contam com atuações de tirar o fôlego que você precisa conhecer O post 5 doramas com boas atuações para você assistir e se impressionar apareceu primeiro em Recreio.
0 0 0 0
Post image

Level Up Your Emoji Game: A Command-Line Shortcut for Making Custom Slack Emojis Custom Slack emojis are a big part of Atomic Object’s culture, with everyone developing their own emojis and funny...

#Extracurricular #Activities #python #slack #emoji #personal #project

Origin | Interest | Match

0 0 0 0
Post image

Level Up Your Emoji Game: A Command-Line Shortcut for Making Custom Slack Emojis Custom Slack emojis are a big part of Atomic Object’s culture, with everyone developing their own emojis and funny...

#Extracurricular #Activities #slack #emoji #personal #project #python

Origin | Interest | Match

0 0 0 0
Post image Post image Post image Post image

This month's Drama Club saw over 50 pupils gather together to 'spooky it up' with our Halloween stage make-up extravaganza.

The most creative and spookiest faces were awarded well-earned house points.

#WHSDrama #Opportunity #WeAreWHS #Extracurricular

0 0 0 0
Preview
5 doramas com protagonistas adolescentes Com protagonistas adolescentes, estes 5 doramas farão você lembrar das angústias e felicidades que surgem após a infância acabar; descubra! O post 5 doramas com protagonistas adolescentes apareceu primeiro em Recreio.
0 0 0 0
Post image Post image

Phase 1: mapping temperature 🌡️ in Turlock as part of a volunteered project for Urban #Geography #Environmental Sustainability course @stanstate.bsky.social #extracurricular #fieldwork

2 0 0 0
Post image

Great netball skills, getting ready to perform at the festival next week! #extracurricular #ESSD2025 #BeActive #BankheadWillSOAR

1 0 0 0
Post image Post image Post image Post image

Our first Junior Languages Club of the school year!

Pupils had lots of fun at this month’s French-themed session, creating their own versions of the Eiffel Tower — with a little help from our Modern Languages Mentors.

#WHSModernLanguages #Opportunity #Extracurricular

0 0 0 0
Post image Post image Post image Post image

⬆️ New Extra-curricular club alert!! ⬆️

It was a great first session in the ‘Creative Hub’ this week making hand made note books. Awesome creativity on show from this bunch!! 💜 #Creativity #Enrichment #AfterSchool #ExtraCurricular

0 0 0 0
Preview
10 Most Overlooked K-Dramas, Ranked My Mister, Dr. Brain, and Prison Playbook are all among the absolute best K-drama shows that are sadly underrated and overlooked.

Movie TV Tech Geeks #TV #SouthKorea #MyMister #Extracurricular 10 Most Overlooked K-Dramas, Ranked

0 0 0 0
Post image

Only 2 weeks left! We’re finalizing our Fall roster soon—don’t miss your chance to join this rockstar session. Sign up today 👉 https://ctcharlotte.org/Online/article/theatre-classes

#AfterSchool #TheatreEducation #DanceEducation #ExtraCurricular

0 0 0 0
Video

From the hearts of our students, to your feed ❤️📲
#RealWords #Students #ThemeThursday #Differences #Learning #Extracurricular

0 0 0 0

Nu ga ik Geert natuurlijk nooit gelijk geven. En ik maak zeker geen onderscheid.

Dus ik zeg, álle (basis)onderwijs seculier. Religie-onderwijs doe je maar in je vrije tijd #buitenschools #extracurricular

1 0 1 0
Video

Do you agree?🧐🤨

#extracurricular #acitivites #kids #onlineclasses

0 0 0 0
Post image

We don't teach... We mentor... Which means we connect, we engage and we empower, so that our students feel their worth and develop their skills 😜🤩👾

#Independence #extracurricular #ThemeThursday #FormingConnections.

0 0 0 0
Post image

Our students are at the centre of everything we do, we show up for them... Our students make Imbue... Imbue…😙👾✨
#PersonCentred #Extracurricular #TeamImbue #MentorMonday #Students

0 0 0 0
Video

No cuz deadass I thought this drama was going to end completely differently… the writers absolutely hated the main lead. He had an awful life from jump and they made it get worser and worser every eps lmao. #Extracurricular #Kdrama #KdramaChat

1 0 0 0