Lab notes #020 useDb and Embodied

Lab notes #020 useDb and Embodied

This week the todo list is coming along. The app works like a regular todo list. There's no server, and yet it persists the data between reloads.

I wanted to see how it would feel to have a database as the state management library. Instead of having an app state represented as a POJO that you manually fetch data out of the server and insert into it, I wanted the app state to just be the database. It resulted in this:

export default function Home() {
  let db: Db<Task> = useDb(migrations);

  let tasks = db.useQuery(`SELECT * FROM tasks ORDER BY created_at DESC`, []);

  const onCreateTask = useCallback(
    (title: string) => {
      const newTask = { title, isDone: 0 };
      db.insert(`INSERT INTO tasks (data, latest_crdt) VALUES (?, ?);`, [
        JSON.stringify(newTask),
        Automerge.save(Automerge.from(newTask)),
      ]);
    },
    [db]
  );

  return (
    <main
      className={`flex min-h-screen flex-col items-center justify-between p-24 ${inter.className}`}
    >
      <TaskCreator onCreate={onCreateTask} />
      <ul>
        {tasks?.map((task: Task, idx: number) => (
          <TaskLine key={task.id} db={db} task={task} />
        ))}
      </ul>
    </main>
  );
}

At the moment, it's not incremental at all, and just relies on querying the database again on insert. But since it's local, it feels great when adding tasks. The affordance so far is a thumbs up. I no longer have to worry about representing data in different ways between the client and the (yet-to-be-written) server. The main affordance that worries me later is how giantic an SQL query can be, and a strict SQL string template is hard to compose and break down.


The other thing I discovered is that I really want a db extension to handle the syncing for me. In order to make it work, the data schema is less than ideal. It's set up as a JSON object with a Automerge doc along side of it, and then use Cambria to handle the schema changes. I still have my eye on CR-Sqlite and Evolu, but so far, I've been able to make progress without them.

Right now, I've also been thinking about how an embodied spatial interface might work.

I've discussed this with GPT-4, and it offers some things, but a fundamental compelling reason still eludes me, even though I feel intuitively compelled towards working in this kind of environment. If you have any thoughts on this, let me know.