Pat David Avatar

Switching Themes

I got the bug recently to finally do something that’s been annoying me for some time: set up a dark theme for this website that is user selectable and that will persist.

Normally I prefer the white background (default) that I originally designed but I understand that some prefer a dark background. When it’s in the evening and I want to write/edit a new post (like I’m doing right now) so do I. When it’s daytime, though, I prefer to be back on the white background.

The Dark (Style)

Creating a dark version of the site is relatively easy. I originally styled things sparingly here to keep it light and simple.

The Dark by Lemony Snicket - I love reading this book to my kids (you should hear me do the voice for the dark).

With plenty of thanks to past-Pat for being proactive there aren’t many rules to change to make a dark theme work. Here they are:

body, hr:after {
    background-color: #222;
    color: #ccc;

h1, h2, h3, h4, h5 {
    color: #eee;

code, pre {
    background-color: #111;

That’s pretty much it. I set the body backgorund-color and color to dark versions (the hr:after is for the new horizontal rules I added a few days ago).

The headings are slightly brighter than the body text (just like how they’re slightly darker in the light theme) and the code blocks use a darker background. The link text colors were tweaked from looking at the Solarized color scheme by Ethan Schoonover so they were already on the path to being used in either light or dark versions and didn’t need modification.

I went with a more neutral dark gray background vs. the slightly blue-tinted Solarized background because I didn’t want the background to clash with any photos I share.

Applying the Styles

The application of these styles was pretty straightforward. I had all of the main styles for the site load first (in the document <head>), where I set the dark theme as part of my default styles. Immediately after these default styles, I added a new <style> element that actually set the colors to the light theme version.

I did it this way because later I will talk about the JavaScript I use to switch the styles as well as add persistence for whatever a visitor chooses. This way if a user has JavaScript disabled they will get the light theme by default.

The pseudo code for my styles now looks like this:

    ... default styles for everything
    {dark theme rules}

<style id='lightcss'>
    {light theme rules}

This will make sense a little later.

Inverting Colors

As an aside, while looking around at others works to see if I was missing something, I came across an awesome method for creating a dark version of a website. It’s in the blog post A Theme Switcher over on the Inclusive Components site and it’s an elegant use of the invert filter.

The post is well worth a read, but the general gist is to use the invert filter to invert all of the colors on a site. They explicitly give a background color to the :root html element, and then trickle it down to all other elements on the page through the * selector (so you don’t end up with white text on a white background). A little selector magic to avoid images and videos and you have a very tersely implemented theme inversion!

Here is the final CSS they used:

:root { 
   background-color: #fefefe;
   filter: invert(100%);

* { 
   background-color: inherit;

img:not([src*=".svg"]), video {  
   filter: invert(100%);

Wonderful! I almost went this route as well, but my colors are not quite set to be how I’d like them as straight inversions. I will keep this in my bag of tricks for later though!

Theme Switching

I now needed a way to allow visitors to use this new theme. A small bit of JavaScript at the end of my pages takes care of enabling/disabling the default light theme colors:

    document.getElementById('theme').addEventListener("click", function() {
        light = document.getElementById('lightcss');
        if( light.disabled == true ){
            light.disabled = false;
            light.disabled = true;
            localStorage.setItem("theme", "dark");

I attach an event listener to a link on the page (see the “Theme” button in my header). Targeting the lightcss style element, we can toggle it through the disabled attribute. This might seem odd if you’ve done this before.

Normally you’d probably consider setting the dark/light rules and applying them to a class. Then you’d toggle them by adding/removing the classes. While this works great, it tends to be slightly problematic when used for applying stored user preferences…

The Persistence of Memory

You’ll notice in the previous JavaScript snippet the lines that set/remove a localStorage parameter theme. This allows me to remember what theme the user wants.

Persistence of Memory by Salvador Dali.

Another small piece of JavaScript in the <head> allows me to check for the setting:

if( localStorage.getItem('theme') == 'dark' ){
    document.getElementById("lightcss").disabled = true;

This could be done with cookies as well but many folks might have them turned off for security reasons.

This helps get around the problem of using a class to switch styles. If the setting is for the dark theme, it needs to be applied before the page has a chance to load (and show a flash of the white theme). Using the disabled attribute we can set (well, unset) these styles before the page has a chance to render.

Give It a Try

Whew! That was a mouthful. Well, go ahead and give it a try if you’d like! In my header under my name and main site links you should now find a “THEME” link that will swap things around for you. Let me know if anything seems wonky.

Installing Adobe Digital Editions on Linux with WINE

This post is a little more esoteric, but in the spirit of helping others from the future we’re gonna dive into this.

Wisdom of the Ancients
I’ll stop posting relevant xkcd comics when Randall stops making relevant xkcd comics…

I picked up an Amazon Kindle Paperwhite over a year ago, and I have been tearing through books at an alarming rate. In the course of finding more books to read I did what I’ve always done for as long as I can remember: visit my local library.

Side note: Please, please, please support your local libraries. It’s like supporting net-neutrality in meatspace!

I immediately ran into a bit of a disconnect between my rapidly advancing digital life and the reality of digital books.

The problem lies in how we can borrow and checkout digital books. Currently, there are mainly two big systems in place for digital library lending, Bibliotheca’s CloudLibrary and Rakuten Overdrive. As is often the case in modern computing, anything not Apple or Microsoft is relegated to the rubbish bin. As a Linux user, this is not ideal for me.

Neither of these software solutions have a Linux option.

Wine Is Not an Emulator

Luckily for Linux users, there’s the project to run Windows applications on various POSIX-compliant operating systems: Wine.

I won’t go into using CloudLibrary, as it’s not the focus of this post. It actually installs just fine all on it’s own in Wine so it’s a non-issue.

Overdrive is the real problem here. Rather, it’s use of Adobe Digital Editions (ADE) as the means for checking out books. (The actual interface for Overdrive at the library is a website.) For other purposes that I won’t go into here right now, I need to be able to use an older version of ADE. Specifically ADE 2.0.1.

I spent some time researching if the application would work over at the App Database for Wine. The instructions there didn’t really work for me, but there were some other posts in places like the MobileRead wiki where I was able to gain some more insights as well. Overall it took a good few hours of searching and playing to finally arrive at a working installation of ADE 2.0.1 with Wine on Linux.

If you’re still reading this far I can only assume that you need to get this installed as well. Let’s do it!


I have successfully installed ADE 2.0.1 on a fresh installation of Ubuntu 18.04. You’ll need to be comfortable in your shell to do this, no graphical installer for these steps (sorry).

To start, you’ll need a couple of downloads for later:

I just downloaded these directly into my home directory for easy reference later.

You’ll also need to install Wine. I just went ahead and used the package from my distro: wine-3.0 (Ubuntu 3.0-1ubuntu1). You’ll also want a helper script for setting things up automatically in Wine called winetricks, and I also needed cabextract to be able to extract files from a Windows .cab file.

In my case I just did:

$ sudo apt install wine-stable winetricks cabextract

Wine installs everything into it’s own directories that you tell it to (referred to as a prefix). You can easily tell it which prefix to use by setting this in your shell before you run a command. In my examples below I will be installing ADE into it’s own prefix in my home directory called ~/.adewine.

  1. Set up a new 32-bit prefix with Wine.
    You need to setup a fresh install into it’s own prefix, and tell Wine to make it a 32-bit environment:

     $ WINEPREFIX=~/.adewine WINEARCH=win32 winecfg  

    You can also tell Wine to use this prefix for all subsequent commands:

     $ export WINEPREFIX=~/.adewine
  2. Now you need to install corefonts and windowscodecs:

     $ winetricks -q corefonts && winetricks -q windowscodecs

    At this point, I originally found some errors where Wine wasn’t picking up the windowscodecs.dll being installed. I was seeing a bunch of errors like:

    000d:err:module:import_dll Library windowscodecs.dll (which is needed by L"C:\\windows\\system32\\winemenubuilder.exe") not found

    I found that I could fix this by manually copying them to the correct location:

    1. Extract all the files from ~/.cache/winetricks/windowscodecs/wic_x86_enu.exe
       $ cd ~/.cache/winetricks/windowscodecs/
       $ cabextract -d tmp wic_x86_enu.exe
    2. Copy windowscodecs.dll and windowscodecsext.dll into ~/.adewine/drive_c/windows/system32/:
      $ cd tmp/
      $ cp windowscodecs* ~/.adewine/drive_c/windows/system32/
      $ cd ~/
  3. Install the Full .NET 3.5SP1 installer you downloaded previously:

     $ wine dotnetfx35.exe
  4. Finally, you can install Adobe Digital Editions 2.0.1 normally:

     $ wine ADE_2.0_Installer.exe

Et voilà!

That’s it! If there were no errors you should now be able to run Adobe Digital Editions 2.0.1:

$ WINEPREFIX=~/.adewine wine .adewine/drive_c/Program\ Files/Adobe/Adobe\ Digital\ Editions\ 2.0/DigitalEditions.exe
Adobe Digital Editions 2.0.1 in Wine


If you can keep your head when all about you
 Are losing theirs and blaming it on you,
If you can trust yourself when all men doubt you,
 But make allowance for their doubting too;
If you can wait and not be tired by waiting,
 Or being lied about, don’t deal in lies,
Or being hated, don’t give way to hating,
 And yet don’t look too good, nor talk too wise:

If you can dream—and not make dreams your master;
 If you can think—and not make thoughts your aim;
If you can meet with Triumph and Disaster
 And treat those two impostors just the same;
If you can bear to hear the truth you’ve spoken
 Twisted by knaves to make a trap for fools,
Or watch the things you gave your life to, broken,
 And stoop and build ’em up with worn-out tools:

If you can make one heap of all your winning
 And risk it on one turn of pitch-and-toss
And lose, and start again at your beginning
 And never breathe a word about your loss
If you can force your heart and nerve and sine
 To serve your turn long after they are gone,
And so hold on when there is nothing in yo
 Except the Will which says to them: ‘Hold on!’

If you can talk with crowds and keep your virtue,
 Or walk with Kings—nor lose the common touch
If neither foes nor loving friends can hurt you
 If all men count with you, but none too much
If you can fill the unforgiving minut
 With sixty seconds’ worth of distance run,
Yours is the Earth and everything that’s in it,
 And—which is more—you’ll be a Man, my son!

Rudyard Kipling
Rewards and Fairies, 1910

Password Management

The virtue of being forgetful

I suck at passwords. To be fair, so does everyone else. Everyone else being bad at passwords doesn’t help me, though. It only increases my awareness every time I hear about the latest data-breach, password leak, or programming error.

The thing is, I know what I should be doing, but the one-two punch of laziness and procrastination constantly seem to beat me into submission.

xkcd: Password Strength
Relevant xkcd. Yes, I know it’s old. Yes, it’s still perfectly valid: math is math.

I know I should be:

The problem is that doing those things is hard. I rely on muscle-memory helping me with passwords that I have to use multiple times every day. I have trouble remembering my anniversary date, much less the complex password for a website I log into once per quarter (October 25th in case my wife is reading). I can measure some of my password ages in years.

Password Reuse
An even scarier relevant xkcd

Sure, I can abuse the “Forgot Password?” button on any of the myriad of sites I might visit and forget about, but that wreaks havoc when I have accounts tied to apps. Particularly mobile/phone apps.

Luckily, there is a solution.

Password Managers

I avoided using a password manager for a long time. I’m not really sure why. Partially out of paranoia and FUD, and probably a bit of worry in giving up control over so many logins. The trick was to realize that I’d be able to replace all of my usernames+passwords with a single master password.

I had a couple of convenience factors that I needed to be available before I could make the switch, though:

There are several well-regarded options for password managers out there, including popular ones like LastPass and 1Password but they’re not Free Software.


KeePassXC Logo

After a big of digging I finally heard enough good comments about KeePassXC that I figured it was worth a shot. After about two months of using it, my main thought is: why on earth did I wait so long to do this?

The project is Free Software (GPL) and was forked from KeePassX due to stalled response from its single maintainer.

It keeps your passwords in a local encrypted file (AES, Twofish, ChaCha20). They’ve got clients for all the major OS and there’s an iOS app (MiniKeePass (iTunes), also GPL). There’s also a browser extension that communicates with the client allowing access to passwords right in the browser, securely. If the URL is listed with my database entry, it prompts to fill in the username/password for me when I visit the site.

It’s now trivially easy for me to make all of my passwords quite complex (or at least with a nice high entropy of at least 90bits or more). If I’m really concerned about possibly having to manually enter the password somewhere else, I can make arbitrarily long and random passphrases as well (i.e., cold riverbank outcome shrubbery display stoplight upfront).

What’s great is that thanks to my new Nextcloud server, I keep the password file there to sync with all of my machines (even my iPhone). It’s also wild to see just how many logins/passwords you accumulate in your digital life (I’m up to about 65 unique entries at the moment - and most of those would have been variations or the same password not too long ago!).

KeePassXC Browser Integration

The most important part of making this a frictionless adoption is having integration with your browser. Luckily the KeePassXC team have created browser extensions for both Chrome and Firefox to make it trivially easy to use. With the extension installed you can just visit a site and if you have an entry for it in KeePassXC it will prompt you to automatically fill in the username and password.

There’s a Chrome extension as well as a Firefox extension available. They both allow for encrypted message passing between the browser and the KeyPassXC application. This is similar to having the browser remember passwords for you but with the benefit of being cross-browser compatible if you need that sort of thing as well as allowing you to store arbitrary passwords for things not related to a web login.

The extension also offers to add usernames/passwords for you if it’s for a site that is not currently in the database, which is a nice touch.

Easy on the Brain

Ultimately what this means is that my cognizant load can be reduced by quite a bit. I only need to remember one good passphrase/password. In the case of my phone, I can even let biometrics manage that for me. All while my actual passwords can be much more complex and safer.

If you want to take a huge burden off your digital life while making your world more secure at the same time, I’d highly recommend checking out a password manager (seriously, KeePassXC has been great but go with whatever you’re comfortable with).


It was pointed out to me after publishing this by on Mastodon that KeePassXC is one of the tools that the EFF recommends for Surveillance Self Defense (this entire site is well worth a read).


I finally got around to setting up my own Nextcloud!

I’ve been a file-syncing service user for a long time. There’s just so much convenience in services like Dropbox and Google Drive. File syncing and access across all of my computers and devices is awesome. The ability to automatically backup all of my phone photos to the account is also awesome.

However… Only having 7GB of available space is not awesome. Relying on a third party to control and protect my data is not awesome. Between space and privacy, I certainly didn’t want to take advantage of automatic photo syncing (particularly with all of the associated metadata and geodata for each image). The theory is great, but the implementation leaves a little to be desired, especially if you care about privacy (which I’ve written about previously).


My normal uses for a file-syncing service are pretty typical, I think. I’m a big fan of being able to continue computing how I want no matter which machine I happen to be on (work, home, laptop, etc…).

I’ll use it as a temporary file sharing location for quick and easy access (for myself between computers as well as for others). This is particularly helpful when collaborating on something or sharing quick mockups or images with friends and family.

I use Calibre to manage my ebook library, so I keep the entire folder structure there. This gives me access to the library from any other computer, particularly handy when I just need to add more books or transfer them to my devices.

I also finally switched to using a password manager, KeePassXC. It keeps your passwords in an encrypted file, and to maximize its usefulness I need access to the password file on all of my devices, so I’ve been keeping the file on my old Dropbox account.

Really, my main two complaints about using an existing service like Dropbox or Google Drive is storage space and privacy. Luckily, rolling my own service using Nextcloud on my own server solves both of those problems while keeping all of the other advantages.

Enter Nextcloud

I already have a server (Ubuntu 16.04) at home I use for Plex. There’s not a huge load on this server usually, so I figured I’d go ahead and add Nextcloud to the mix.

Nextcloud webpage screenshot

This was way simpler than you might think (though less simple than using the snap). I basically followed the excellent guide from Jason Bayton on installing Nextcloud with:

As Jason writes in the beginning of his page, after completing the guide I had: Nextcloud login

The project has a client for all major operating systems including my phone (iOS), and appears to have feature parity for the most part (or at least the parts I’m most interested in, anyway). Including the all-important phone-photos automatic upload. Selective sync is one of those features that’s a must-have for me (no need to sync all of those phone photos to all of my other clients).

The web interface is quite nice, and pretty snappy once the caches are built (even when trying to view directories of images in a ‘gallery-style’).

There’s a pretty nice app store available for different ways to extend your installation. One of my favorites is the Notes app that provides a nice, distraction-free writing interface that’s markdown aware.

Overall the setup was a breeze (and, dare I say it, fun?). That’s one less intrusion into my digital life, and one more way for me to take back a little control…

Libre Graphics World

Writing is hard. Just look at the post dates for my own blog posts to see what I mean. It takes discipline and hard work to put together any sort of non-trivial writing. If the topic is about a community as diverse and loosely collected as Free Software projects then the effort is exponential. Most Free Software projects don’t have a media/public relations person to interact with.

Libre Graphics World Logo

Today I wanted to talk briefly about both a writer and a PR person: Alexandre Prokoudine and what he’s doing over at Libre Graphics World.

Alex is the main PR person for GIMP and he’s also the guy I turn to when I need or want to publish something for the project. This is just one hat he wears (there’s many others), but those aren’t the reason I’m writing about him today.

LGW header image

Today I’m referring to his work as a journalist. Alex created Libre Graphics World back in 2009 to cover the rather diverse ecosystem of Free Software for creative professionals. The value in reporting at LGW is the time and research spent not only digging out the most interesting bits of news, but also taking the time to interview people in the projects. The reporting is nicely in-depth and explores various aspects of issues beyond simply copying the changelogs (see his recent article on the recent fork of Valentina, Seamly2D as an example of the depth and background provided in his articles or his awesome review of features for the GIMP 2.9.2 release).

I think this type of reporting and community highlights is extremely important to a healthy Free Software ecosystem. Especially one that focuses on projects for creatives and that spans so many genres.

Alex recently stopped running ads on the site and has now switched over to using Patreon to fund his activities. I think this is a great time to head over to his Patreon page and throw a few dollars a month to help him do what he does! Every little bit helps!


Happy New Year!

Way back in May of 2017 I made my first commit to start a new project for some friends of mine. Seven months later and we were finally able to publicly push the results: a new website for the awesome folks at darktable! (I already published a post about this on the darktable blog.)

darktable logo

Mastodon (Toot! Toot!)

So, I’m on Mastodon. Well, I’ve been on Mastodon for a while now, but thought I’d talk about it briefly here.

On most modern social networks, you are the product. Your habits, friends, and interests are all consolidated, packaged, and sold to anyone willing to pay a few bucks to rent your attention (whether you like it or not). If not you directly, then your habits, likes, dislikes, age, gender, sexual orientation, and the same information for all of the people you may know (including ones you may never had connected on that network).

It’s ridiculous what information you’re giving away for advertisers and marketers to exploit.



I updated some old GPG keys last year after using the same 1024-bit RSA key from 2004. (Honestly, I was just impressed that I managed to dig up the private key in order to revoke it.) I had set the new subkeys to expire every year, and while renewing them I took another look around to see if GPG/encryption had gotten any easier.

As usual, relevant xkcd.

It hadn’t.


My Muse

My wife needed a headshot recently for a work related thing. So I broke out some old and simple equipment to do a quick impromptu shoot for her. This is one of the outtakes from that shoot (she didn’t like how her hair looked in this shot so it wasn’t used).

Dot headshot
Dot. (On Flickr) ƒ/6.3 50mm 1250 ISO200

← Older Posts