awarm.spacenewsletter | fast | slow

Interfaces and Running out of Yaks

If you're new to this newsletter, it's currently chronicling my attempt at building my own thinking infrastructure, which happens to be a perfect way to yak-shave my way out of actually having to think. But, I have to think about interfaces for thinking, which is almost as hard, and so to yak-shave my way out of that, I conjured up fun technical challenges that "had" to be done first.

First, I implemented an append-only log of events creating and updating notes. On top of the log you can instantiate views which process it and expose different ways of viewing your collected thoughts. This forms a stable foundation for future experiments.

Halfway through that feature I got seduced by another fun challenge, Reactive Queries. Basically, if you ask a view a question ("Give me all the notes that link back to this one") and the answer to that question changes, the query should "react" to that change, and give you the new answer. You can do this by tracking the data accessed during updates and queries, and keeping track of which queries touch what data. It's really fun to implement, as it seems like magic in use, but can be accomplished in <50 lines of code.

Starting to interface

After a couple weeks of work I've got those two in place and working!

Now, I've run out of yaks and I've got to start thinking about what it'll actually be like to use this program. I've got reactive queries, so, I got to start thinking about a reactive interface.

Which of course means thinking about React1. I've talked about my love for the web-framework before, but for this particular project it actually presents me with a bit of a conundrum. As you may have noticed, I'm taking a lot of joy in implementing the specific gnarly bits of everything myself. So, I've been implicitly been holding a zero-dependency vow.2

Why zero-dependencies?

I think I first started toying with it as a goal after seeing the latest iteration of Devine Lu Linvega's static wiki engine Oscean. It's written entire in ANSI C, depending only on the standard library, and is designed for low-power, offline first devices. This is a necessity because, as one part of 100 Rabbits, Devine spends a significant amount of time on a sailboat, building thing following their philosophy.

While I don't have quite as developed a philosophy for this project, zero-dependencies is still an attractive aspiration. It's just incredibly satisfying to know every part of a program. When you can't just pull a library in for something you don't fully understand you're forced to feel that ignorance. The only two choices are understand or simplify.

At first I was feeling optimistic about implementing the interface in pure javascript, inspired by "A little bit of plain javascript can do a lot" from Julia Evans. But, I quickly began to miss the declarative react way of doing things.

If I wanted to stick to my principles I could re-implement react from scratch for my purposes (there's this amazing tutorial by Rodrigo Pombo to guide me through it). But, I think this is where I stop with the yaks. I need to get to something I can actually use, and it's ridiculous to re-implement something that works exactly the way I want it to.

So... what's the actual plan for the UI?

Phew, with that off my chest let's get to it. There are two categories of things I want to do:

Note the lack of things I want and know how to implement. That wouldn't be any fun.

In the first category go things like backlinks, keyboard driven navigation, auto-complete, and nice-looking text.

For the latter the first main area I want to explore are defining new interface elements from within the program itself. This stems from the original spark for fancynote, a language for writing notes and programs to manipulate those notes. Well, those programs need an interface of some kind!

Ideally there's a way to progressively build up that interface over time to be more useful to you. I want to something like this, say for making an interface to look at all the information on books in my notes.

  1. Just write some code to do whatever I'm trying to do and see results immediately
  2. Turn that code into a function I can run whenever I want
  3. Attach that function to a rendered interface in React to see it's output or to a keyboard shortcut to trigger it.

There are a ton of open questions at every stage of this. Where do you run the code? How are results represented? Where do we keep track of defined functions, keymaps, and interfaces?

Ideally all of these fit into the Log paradigm, and can somehow exist just as notes and views. Honestly, I have no idea!

This coming week I'm going to keep these thoughts in the background, but my primary goal is to work on things in the first category of things, mainly backlinks and nice-looking text!

Catch you then, Jared


  1. Never mind that react is not reactive
  2. Okay well, I depend on a couple things. Typescript, to compile my code to javascript, Snowpack, to set up my code to run in the browser, and of course the web-browser itself, which is a massive, very opinionated, dependency.