I have wanted to build an app for myself that publishes a collection of notes and borrows some UI ideas from Andy Matuschak’s notes website.
At first glance it looks like Turbo Frames could be a really good fit, but after a bit of investigating, I’m not so sure. Posting this here in case anyone can point out a way of achieving something like this in a Turbo Frames way.
Background:
When you visit https://notes.andymatuschak.org/ in a desktop browser it provides a lovely means of navigating a collection of linked notes. Clicking a link in one note opens the next note in a new column, without replacing the note you are already viewing. This is a lot like the Column view in macOS Finder. You can create an arbitrary number of columns, each with a separate note by navigating through the links. Here is a screenshot:
Achieving this using TurboFrames:
When I saw Turbo Frames, I thought this could be a good fit. Each column could be a new Turbo Frame and lazy-load the next note as the user navigates via the links embedded in each note.
Too keep things simple, I would like to find a solution that can be hosted as a static site with each note as a separate HTML file:
/note-a.html
/note-b.html
/note-c.html
…
Here is my first thought about how this would be done using Turbo Frames:
- The user could start by navigating to any note. For example
/note-a.html
. The page would start with a single Turbo Frame (Frame 1) wrapping the main content ofnote-a.html
. - When the user clicks a link in
note-a
to another note (for examplenote-b
), a new Turbo Frame is added to the DOM using javascript (Frame 2) and lazy-loads the content ofnote-b
.
This is where Turbo Frames starts to look less useful for this application… Two problems:
-
Getting javascript to add and remove Turbo Frames to the DOM feels like it is working against the simplicity of Turbo Frames and the ethos of Hotwire in general. The JS required would be more than just a “sprinkle” (to use DHH’s words ).
-
Turbo Frames that are lazy-loaded need to matching
id
of the Frame they are replacing. In this caseFrame 2
would need to have anid
that matches theid
of the Turbo Frame wrapping the content innote-b
. This means that we would need to know theid
of the Turbo Frame onnote-b.html
before addingFrame 2
to the DOM ofnote-a.html
.
Neither of these make Turbo Frames impossible to use for this use-case. But these challenges feel like Turbo Frames might not be a good fit. The attraction for me is the simplicity, so I’d like to avoid working against the grain of Turbo/Hotwire.
A solution to problem 1 that avoids manipulating the DOM too much might be to include a bunch of hidden Turbo Frames that are just revealed when needed.
Problem 2 could be solved by using a more dynamic back end that stores the note content in a database and wraps the content with a Turbo Frame with an ID that matches the Frame on the client (for example frame-2
). I would love to avoid building a dynamic back end though!
Very interested to know if anyone has any thoughts or can suggest an approach that is more in line with the Hotwire / Turbo framework.