Ben Crowder

Blog: #pwa

6 posts :: tag feed :: about the blog :: archive

Saturn intro

Another entry in the frankly too long series talking about my personal productivity tools.

Saturn is my launcher app for my phone. It’s a small Go web app. The name comes from the Saturn V rocket launcher, and I wrote it as a replacement for Launch Center Pro (when it switched to a subscription model, because apparently I am allergic to those).

Overview

This is what it looks like:

saturn-1.png

The blue buttons are direct links to pages. There’s a very hard to see dark textbox at the bottom, and if I type something in there, the green buttons take that and execute a search somewhere else. Finally, the pink buttons open secondary panels, like this Notebooks panel:

saturn-2.png

On this panel, the lighter rectangle above the buttons is a search box that allows filtering through Vinci notebooks.

How I use Saturn

On my phone, I have it saved to my dock. It’s not set to be a PWA, because then the links would open in the in-app Safari; I prefer having them open in normal Safari.

I use Saturn pretty much every day. I mainly use it to set reminders, search Amazon, Goodreads, and eReaderIQ, and get to my journal and my daily review list.

The future

I’m largely happy with it as-is. Maybe some more refactoring of the buttons (the Search button is largely obsolete now that I’ve moved all those buttons to the main screen, for example), and it could use a little design love to make things more consistent (search boxes, for example), but that’s it.


Reply via email or via office hours

Storybook intro

Still another entry in the will-it-ever-end series talking about my personal productivity tools.

Storybook is my fiction writing app. It’s a Python app running Django. The name comes from, uh, books with stories in them.

Overview

First, the dashboard, which lists weekly writing stats and active stories at top and backburnered stories at bottom:

storybook-1.png

The writing view has a stats bar at top (showing how close I am to meeting my daily 1,000-word goal) and then the textbox for the actual writing:

storybook-2.png

The menu has some overall story stats and an outline (with somewhat vague and hopefully unspoilery scene titles), and some admin links:

storybook-3.png

Syntax

As you can see from the screenshots, it expects Markdown. I’ve put in a convention hack where h2 tags (##) delineate scenes. Also, scene titles that begin with “Chapter X” create chapter divisions. (Clarification: a story has a flat list of scenes. The chapter divisions are display-only.)

How I use Storybook

On my laptop, I have it open in Firefox as a pinned tab. On my phone, I have it saved to my homescreen as a PWA.

I mostly avoid using Storybook (cough) but somehow still manage to put in a thousand words a day, one word after another.

There’s a payload syntax so I can send writing from Gate or Quill to Storybook, but I never use it.

The future

Same old story: I’m planning to move it to FastAPI and start using plain text files for storage instead of a database.

At some point I want to refactor the outline UI and add search functionality.


Reply via email or via office hours

Bookshelf intro

Yet another entry in the forever-long series talking about my personal productivity tools.

Bookshelf is my reading tracking app. It’s a Python app running Django. The name comes from, uh, the thing that holds books.

Overview

Behold the books:

bookshelf-1.png

At the top there’s the stats panel, which shows how much I read the last six days with color coding for the genre tags (and yes, Wednesday and Friday I didn’t meet my 100-pages-per-day goal), my page total so far this month (932), how many books I’ve finished so far this month (2), and how much of my reading this month has come from each tag (I usually try to read around 50% nonfiction, but I usually fail).

And then there’s the book list itself. Title, progress bar with some extra data (including how long since I started the book), current page number (clicking this opens a panel where I can record the page I’m on along with a comment), and how long it’s been since my last entry.

Each book has a staleness limit (default is five days), where if I haven’t read the book at all in that period of time, it changes the color of the title to a glaring, awful red, and that’s sufficient motivation for me to get back to that book. (To be honest, lately I haven’t seen it come up much since I’ve been reading only a few books at a time, but in those crazy days when I was reading twenty to thirty books at a time, I saw it a lot.)

Also: the sixth book (in case you were wondering) is A Disciple’s Life, which is only visible on Sundays (I reserve it for Sunday reading).

And the mobile view, for the heck of it, and since it’s the one I use almost all of the time:

bookshelf-1mobile.png

There’s also a stats page, since the statistics are surprisingly helpful in motivating me to make time for reading:

bookshelf-2.png

(Yes, as of a couple days ago I’ve read more this year so far than all of last year in total. This makes me inordinately proud even though it really doesn’t matter.)

And, lastly, the hopefully self-evident history page:

bookshelf-3.png

How I use Bookshelf

On my phone, I have it saved to my homescreen as a PWA, and that’s primarily where I use it, since I mainly read on my phone these days. On my laptop, I have it open in Firefox as a pinned tab.

I use Bookshelf every day to track my reading, both for individual books and for my daily/monthly reading goals. It’s handy, too, as a bookmark that toddlers can’t pull out.

The future

The desktop view needs some love, particularly that stats page. (I added those genre tags to it a month or two ago and realize now that I never actually looked at the desktop version. Whoops.)

Also (this should be no surprise by now), I’m planning to switch it to FastAPI along with plain text files for storage, for the same reasons I gave in those other posts.


Reply via email or via office hours

Momentum intro

Another entry in the neverending series talking about my personal productivity tools.

Momentum is my daily goal app, for keeping a goal chain/streak going. It’s a Python app running Django. The name comes from the momentum that a long streak gives.

Overview

Goals can be either binary flags (whether I did it that day or not) or timed (in which case Momentum keeps track of the time spent). The default mode is focus mode, which shows only the top unfinished goal at a time and looks like this (with dummy data):

momentum-1.png

The thin red line along the top is a progress bar showing how close I am to finishing my Momentum goals for the day. The red boxes show the last few weeks of the streak, the green box at the right is the button for saying I’ve completed that goal for the day, and the blue text under the goal name shows how long the total streak is.

When focus mode is off, it looks like this:

momentum-2.png

You can see a partially completed timed goal along with a binary goal. Momentum also supports ignoring goals for Saturdays and/or Sundays (the gray boxes among the red), which I use for things I don’t usually do on the weekends.

When the timer on a goal is running, the favicon changes and the page looks like this, with the pink box at right showing the elapsed time for the current session:

momentum-3.png

(The idea with the timer is that it may take multiple sessions spread throughout the day to meet the daily goal, by the way — if I wanted to make sure I spend an hour writing each day but don’t usually have time to do it all in one block, for example.)

How I use Momentum

On my laptop, I have Momentum open in Firefox as a pinned tab. On my phone, I have it saved to my homescreen as a PWA.

I use Momentum every day for my morning routine, primarily on my phone. The goals I put into it (as opposed to just adding things to my to-do list in Liszt) are things I want to do each day and, to some degree, are things I might not do if I didn’t have a streak pushing me forward (thus “Momentum”).

The future

I’m happy with the app as it is, but I’ve been thinking about merging it into Liszt, since goals like these are fundamentally to-do items. (Every morning Liszt already automatically adds all the items in my ::streak list to my ::today list, so that I can work off my to-do list without necessarily having to go back to Momentum as much.)

Giving Liszt items the ability to be timed is already in place with belt mode, so I’d just need to add the ability to keep track of both partially finished goals and total streaks. Seems worthwhile.


Reply via email or via office hours

Gate intro

Yet another entry in the seemingly endless series talking about my personal productivity tools.

Gate is a small quick entry app for my phone. It’s a Go web app, and the name comes from it being a gateway to my other apps. I used to use Drafts, but when it switched to a subscription model I decided to do my own thing (which worked out well for me, since I was able to make other customizations I’d long been wanting to make).

Overview

The main screen looks like this:

gate-1.png

Just a textbox and some basic controls at the bottom. When I tap the Submit button, it opens up a dialog with options for where to send the contents of the textbox (the payload):

gate-2.png

Red buttons go to Liszt, blue to Vinci, green to Slash. And this is why I have the text-based payloads in all those apps.

How I use Gate

I have it saved as a PWA to the homescreen on my phone, nestled safely in my dock. I use it all the time. (I suppose I could use it from my laptop web browser as well, but I have Quill for that use case, so I never do.)

The future

I’m happy with the app itself. There are, however, some recent bugs with text controls in PWAs in iOS Safari where the keyboard either won’t come up or can’t be dismissed, but that’s out of my control. Hoping those get fixed soon (they didn’t crop up until sometime in the last year or so, I think).


Reply via email or via office hours

Liszt intro

First in the series introducing my personal productivity tools. Buckle up, this is going to be nerdy. And long.

Liszt is my to-do list app. Named after the composer, though I regret it a little since I butcher his name by pronouncing it lisht to differentiate it from the ordinary list. Heresy. The next version will have a better name, though. It’s a Python app running on Django.

Disclaimer: I don’t think this app is perfect. (Or any of the other tools I’ll talk about, for that matter.) I’ll describe things as they are, acknowledging here that there’s a lot of room for improvement.

Overview

This is what the dashboard looks like, populated with some dummy data:

liszt-1.png

And on mobile, where the controls move to the bottom for easier access:

liszt-1mobile.png

The top bit is my stats panel, with the data pulled in from my other tools’ APIs. Daily writing counts, daily words left, total words written on the novel (all three from Storybook), daily pages left (from Bookshelf), and daily goals left (from Momentum). I’ll cover those tools later.

There’s also a slide-in menu on the side, with my most commonly used top-level lists:

liszt-2.png

Double-clicking on a list item opens up an edit panel, which also allows me to move the item to another list with some commonly used lists included as buttons (this whole panel is kind of clunky and needs improvement):

liszt-7.png

Payload syntax

The basic idea behind Liszt (and this is common to many of my apps) is the text-based payload, which enables some nice cross-app integrations (more on this when I cover Gate and Quill). Adding items looks like this:

liszt-3.png

A Liszt payload (the text entered into the add tray) has one item per line, with optional blank lines and optional list specifiers. If there’s no specifier, it’ll assume the current list if there is one, otherwise it’ll default to ::inbox. (I use the double-colon prefix to mark lists, with a slash to specify sublists.) Here’s a fuller example of the syntax, again with dummy data:

Process email :5
Review the merge requests :10

::work/notifications
Read up on Python futures ::: https://docs.python.org/3/library/concurrent.futures.html
Refactor [::work/notifications/refactor]
Write up the design doc

The first two items (which have belt-mode durations, I’ll explain those in a minute) would go into the ::today list (which is the dashboard list). The last three items would go into the ::work/notifications list, as pictured here:

liszt-3b.png

Of these, the first line sets a subtitle by putting it after the triple-colon marker. I use this all the time.

The second line is a symlink of sorts, pulling in the top item from the linked list (different meaning here) and showing it in place, with the Refactor text shown as the subtitle. I used to use this more often but haven’t as much lately.

You can also see that this list has a child list (::work/notifications/refactor).

Belt mode

liszt-4.png

If an item has a duration marker included, that triggers belt mode (ala conveyer belts), as evidenced by the new bar at the top of the screen in the image above.

Brief backstory: I initially wrote an Electron app called Belt that did the same sort of thing, then a few months ago ported it to Go as a menubar app. Shortly after I finished that, I realized it would make much more sense in Liszt and brought the functionality in.

And what is that functionality? It’s just an easy way to time tasks from the list. When I hit Start, it switches into belt mode (also changing the favicon so I can tell that it’s running and turning on focus mode so I can only see the task I’m actively working on):

liszt-5.png

When the timer runs out, it plays a sound and brings up a panel allowing me to continue on to the next item in the list, stop belt mode, or add more time to the timer. (There are also keyboard shortcuts for all of this.)

liszt-6.png

How I use Liszt

On my laptop, I have Liszt open in Firefox as a pinned tab. On my phone, I have it saved to my homescreen as a PWA.

Every morning I go through the main lists and move the items I’m going to work on to the today list. I then work out of the today list the rest of the day, opening it often.

I use belt mode most days, primarily to help me stop avoiding tasks I don’t really want to work on (but that still need to be done).

The future

Lately I’ve grown enamored of the idea of storing data as plain text files in directories, rather than using an actual database like Postgres or Mongo. There are plenty of apps where this doesn’t make sense, but for personal, small tools, it works nicely, so I’m planning to migrate Liszt off SQLite to plain text, and I am very excited about it. Yes, I am that kind of a person.

While Django is fine (we use it at work and I love it), I’m planning to move to FastAPI, which I’m already using for Ditto and Arc. It’s a bit faster and feels more lightweight. I think in my mind I mostly use Django because of the ORM and admin; once I’ve given that up, the baby goes out with the bathwater.

I’m also looking forward to simplifying things, removing vestigial functionality, and sanding down as many of the friction points as I can.


Reply via email or via office hours