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.

First Principles

Over the years, with inspiration from many sources, I have come up with a number of “first principles” or beliefs that guide me on a daily basis. I would like to share these with you here.

Update 2021-11-13: Grouped the principles by a call-to-action, and softened the language to eliminate absolutes.

Follow Your Dreams

1. Every day of life merits planning and purpose. Plan goals for every year, week, and day; work backwards from your goals.

2. Perfection is an enemy; it is driven by others’ perception of you. Embrace chaos; always operate in ‘draft’ mode.

Experience Life In Color

1. Life is about adding value, but it is also about adventure. Do things that scare you; don’t give other people the power to assign value to your work.

2. Emotions are messy, but they also add a lot to life. Let down your guard sooner; get out of your head and say what’s going on in your mind.

Don’t Get Stuck

1. Prioritizing means intentionally dropping the less important stuff. Identify things to drop and shut them down, even if it seems hard to let go.

2. Resistance to action is triggered by fear of failure. Avoid fear of failure by breaking down large goals into smaller, manageable, chunks.

3. Even the smallest chunk of progress keeps the momentum going. Start now to record and track your progress; don’t set the bar unrealistically high.

Do Stuff & Learn

1. Ideas are useless until they are experimentally tested. Build systems; record experimental results in your journal, learn from what you create.

2. Minimalism is your friend. Opt for simple, bare tools to get the job done; eschew sophisticated features.

3. Making mistakes presents opportunities to learn from them. Don’t stick to the known paths, explore new avenues, break stuff to see what happens.

Error Correction

A general technique in teaching an “artificial intelligence” is to feed it ground truth. This may come in many different forms, but the essential idea is this: you help the machine learn from its mistakes by giving it the “correct” answer, and some time to reflect on it.

“I want you to think about what you’ve done.”

This technique works equally well for us humans, as pithily explained in Daniel Coyle’s The Little Book of Talent:

Tip #22: Pay attention immediately after you make a mistake.

Coyle elaborates: “People who pay deeper attention to an error learn significantly more than those who ignore it. […] Develop the habit of attending to your errors right away. Don’t wince, don’t close your eyes; look straight at them and see what really happened, and ask yourself what you can do next to improve. Take mistakes seriously, but never personally.”

In the workplace, most technology companies have some form of retrospective that they codify into a process. At Amazon, this is called a ‘Correction Of Errors’, or ‘COE’ for short. When someone writes up a COE, they write down the nature and import of the error to the business, lessons learned as part of the incident and recovery, and actions to prevent future recurrence of the same class of problems. COEs leverage the 5 Whys process popularized by Toyota for going deeper into the problem and establishing root causes.

I’ve always been a proponent of writing COEs and learning from mistakes. It’s important to see the COE as an “engineering chisel” rather than a “managerial hammer”. As an engineer, writing COEs is a discipline you impose upon yourself to hone your craft.

“Now Look What You’ve Done!”

Some years ago, I proposed the idea of a ‘2 Hour COE’ that was well-received by engineers. It went like this: don’t hesitate to write COEs or think of them as ‘work’; dive right in and do it; don’t spend more than 2 hours to write up a single COE (keep it ugly); focus on root causes and learnings more than anything else; don’t create more than 1-3 action items (avoid creating new work for the team).

Last month, I accidentally missed a meeting with colleagues because my iOS Calendar app wasn’t accurately synced with the Microsoft Exchange server. Someone mentioned “5 Whys” jokingly, and I thought to myself: this isn’t the first time something like this has happened, and I sure keep complaining about it — what can I do to resolve root causes myself? Perhaps I should write up a COE!

Now, I love writing and I spent an hour in the morning with good coffee in hand injecting some subtle humor into the write-up. It was primarily a joke aimed at the guy who mentioned “5 Whys” (and gloriously accomplished the job, if I may say so myself), but last week, it became popular on blind and I got asked by more than one person: was I joking or serious? But can’t it be both? It turns out I did get something really useful out of it after all: I discovered an app called VMware Boxer that is fully supported for corporate email and does work flawlessly on iOS.

If you’re an Amazonian and have questions, join #ama-riyer on the corporate Slack workspace.