Dinky

Today, I want to talk about a small side-project that I’ve been working on (source code on GitHub with an Apache 2.0 license). The project is a minimalistic web application available at dinky.dev that’s open for anyone to use.

dinky.dev has the rather ambitious goal of helping you organize your life. Of course, my original goal was to help me organize my life, and I’m at a stage of the project where I can see it start to do that. I think it would now benefit from others using it, and providing feedback or suggestions.

Daily Rhythms

Something I’ve come to realize over time is that my “planned” daily activities can be boiled down into three simple abstractions, which are note-taking, task-execution, and synthesis.

Note-taking. During the course of the day, I consume a lot of information. My recall and learning are maximized when I write down my thoughts and conclusions, and to this end, I need to take notes somewhere. When there are multiple tools available to do this, I typically grab the closest or easiest one, such as Apple Notes (or a physical notebook), and write stuff down. And because I’m actively listening or thinking at the time, I don’t have the luxury of organizing my notes in any meaningful way.

Task-execution. When I’m ready to get stuff done, it’s most helpful to know exactly what I need to do next. A common pitfall is that the thing I need to do next is too big or ambiguous, and it’s easier to move on to something else rather than think about it. My aspirational rule of thumb is that tasks need to be completable within 20 minutes or less.

Synthesis. Synthesis, a form of deep thinking and planning, bridges the gap between information consumption and action determination. This takes a few forms: (a) given notes captured during the day, what new tasks ought I create? (b) given a large or ambiguous task, what smaller tasks should I break it down into? (c) do the current set of tasks continue to help me make progress towards my larger objectives?

Web Application

dinky.dev is a responsive client-side (React / JavaScript-based) web application that attempts to encode the daily rhythms described above into a single tool that has an optimal user flow. Basically, it lets you take notes and track tasks, and bridges these capabilities with some others that I’ll describe shortly.

The first rule of the application is minimalism. I’ve tried to keep bells and whistles to a minimum, both in terms of style and substance. That’s one reason why the site is themed almost entirely in grayscale. (The second reason, of course, is that I have a bias towards pure functionalism.)

Both notes and tasks support GitHub-flavored Markdown for basic formatting. Markdown is both simple and incredibly valuable for prettifying text and making it navigable, especially when dealing with long hyperlinks. The primary mode of sifting through the data is to perform a search, which is accessible using the forward-slash (/) keyboard shortcut. Search is performed entirely on the client-side, and regular expressions work just fine. All of your data is stored within Local Storage in the browser and accessible only to you (caveat: or anyone who has access to your browser and can pose as you). Besides search, several other functions support keyboard shortcuts, such as the ability to create new items (n) and page navigation.

When you take notes, you eventually need to review and organize them to figure out if there are any further actions that need to be taken. While dinky.dev can’t help you figure this out, it does make it easy for you to add new tasks to your backlog. Furthermore, at the start of the day (or the previous evening, if you’re so inclined) you can identify the tasks that need to get done on that day and add them to your agenda.

Adding tasks to your agenda is a way of separating the planning of your day from the doing of tasks, thus helping you focus on making single-threaded progress. Also, new tasks always go first to your backlog, which is a way of discouraging changes to today’s agenda once you’ve figured it all out.

Topics provide a light-weight way of capturing your core top-level objectives and associating either tasks or notes with those objectives. For instance, as I worked on this project, I tagged related notes and tasks (typically features to implement or bugs to fix) with “#dinky”, which then made it easy for me to pull together everything related to the project. Any word or phrase (without spaces, typically hyphenated) prefixed with a hash (#) is automatically considered a topic.

Limitations

Before using dinky.dev, you should be aware of its limitations. Apart from minor ones that you might discover, there are a few glaring omissions:

  1. No synchronization across devices.
  2. Not a lot of storage (<5MB depending on your browser).
  3. Browser’s “Private Mode” not useful (you can’t save your data).

All-in-all, it’s probably for the best if you treat dinky.dev as an experimental web application and not use it for mission-critical work. That said, it is pretty stable and I expect future changes to be backwards-compatible.

Learnings

Finally, a segue to what I learned from it all.

Synchronizing data is complicated on multiple levels.

…which is why I never got around to implementing it.

First, my preference was to let users manage their data entirely, instead of managing it on their behalf. But this required me to pick a specific vendor that users might be persuaded to use (such as AWS), and require users to set up a complex set of policies for authentication, authorization and storage. And if I did set it up on behalf of users, I would need to figure out how users authenticate themselves to dinky.dev, and how they get billed for their usage. I believe now that some form of account setup on behalf of users combined with cross-account billing might be the best option, if possible in practice.

Second, it’s impractical to use simple and cheap storage like S3 to guarantee correct behavior in the face of concurrent writes. Moreover, things get further complicated when you try to avoid writing an entire blob in favor of incremental updates. The effort (before I abandoned it) started taking the shape of a transaction log (aka “redo” log) to be combined with a subscription mechanism (to keep track of when the log could be merged and optimized).

TypeScript is a lot of fun to use.

This was the first time I’d gotten to use TypeScript seriously, and it certainly hit a sweet spot between compile-time safety and developer-friendliness. I particularly enjoyed its structural typing paradigm, which I think works quite well in a dynamic front-end environment where “everything is data”, and you’re constantly trying to determine if the shapes of objects are fitting together correctly. Also, using TypeScript (+ Visual Studio Code hints) made it easy to develop code without errors; in hindsight, development would likely have been 10x slower without it.

React has come a long way

I initially started writing code using React class components, but eventually rewrote everything using its functional components and hooks instead. React’s architecture made it incredibly easy to decompose and organize code with minimal boilerplate. I stuck to basic features of React, but they were enough to get the job done.

IndexedDB is…complicated

I may yet switch to IndexedDB in the future, but it’s just so complicated! Local Storage on the other hand is probably as simple as it can get (with get, put, clear as the main primitives), but has severe limitations (lack of indexing, limited space). I’ve continued to trudge down the path of Local Storage for now.

Closing Thoughts

This project is not “done” by any means, but it gave me an opportunity to build something that I desperately wanted to use myself. I think that’s a great situation to be in, because it forces you to prioritize what you really need, and you know exactly what it is that you want. I can’t say for sure if that’s a formula for success, but it certainly is a formula for personal satisfaction. Tools that work with you when you want to rewrite large swathes of code (as I did several times in this case) are an essential ingredient to this recipe.

That’s all for today, folks! 🖖

EDIT 2022-05-11: I recently changed the term “tags” to “topics”, as I felt like the latter better reflected the intent of tracking high-level objectives and interests.