Twine 2, why an app?

As a successor to my previous post, which was in the genre of “rushed-changelog scribbled in the five minutes before the plane lifts off,” I’d like to give more details about why Twine 2, having starting as solely Web-based, is now being pushed primarily as a native app — for desktop OSes, anyway. (Mobile ones? Maybe someday.)

Prehistory (or: 2008)

When I first conceived Twine, it would have been possible to build it as a Web-based system– and others had. The one I can recall from that time was called Hypertextopia (by the way, that Chris person in the comments of that blog entry sure does sound familiar — and I wonder whatever happened to that Jeremy Ashkenas fellow who made Hypertextopia). I chose to make Twine a desktop app because I was deeply paranoid about my own creative work. I didn’t want it bound up in Somebody Else’s Website, especially if there was no way for me to retrieve it and re-use as I like. I have somewhat mellowed in the belief since then, but I still hold to it. I think it’s a safe bet that most web sites you encounter will not exist in five years. Hypertextopia doesn’t.

So — to Python I went, and sweated out the details of producing cross-platform apps with wxWidgets. It was (and perhaps is– I am not very well-informed in these matters) a fairly popular option, but it was never very fun. I spent way more time that I ever would have wanted learning the syntax of NSIS — all just to allow people to install Twine on Windows. I would borrow other people’s laptops just to try to fix problems on operating systems I didn’t own (sometimes this was Windows; sometimes OS X). I never had the appetite to figure out how to package it appropriately for Linux, though it was entirely technically feasible to run it there.

A lot of wasted time, in short.

History (or: two years ago)

When I began work on Twine 2, I knew I didn’t want to go back the direction I had taken before, or I would burn out just like before. I flirted with Adobe AIR but all news emanating from Adobe regarding it was ominous, so I decided: let’s do this as a pure web app. Once I understood local storage and saw, miraculously, that JavaScript can trigger downloads (in most browsers, of course — not all), it seemed possible to make a web-based, but not web-hosted version.

That is, although you might use Twine in your web browser, the things you make with it stay on your machine.

I’ll admit, the contradiction in this appealed to me. But it also confuses people who use Twine 2 online, and I think always will. We expect that when we go to http://somewhere, the things we type into our browser go to http://somewhere, and probably be saved there. We’ve been trained to think this way since the beginning.

And, more urgently, because browsers expect web applications to stuff furtive and ephemeral things into local storage — offline caches, user preferences — they give no warning as to how grave it is to delete it.

In the onboarding page of Twine 2, I wrote an explanation of what was going on; even so, I would overhear people on Twitter lamenting the loss of their data and feel like a horrible person. Later, I wrote a whole page of the guide on this topic alone and added large notes trying to draw attention to it.

I think it was as I was wrapping up writing the guide page that I realized:

  • There’s always going to be someone who forgets these warnings or just never understands them, no matter how good a job I do.
  • This is terrible user interface design.

I’m a firm believer that if you write sentences like, “Never do this, or terrible terrible things will happen” in your documentation, you should instead go back to the drawing board and redesign your application so that those terrible things can never happen.

The Present Day (or: last month)

So here we are: a native app courtesy NW.js. It looks exactly like the web version! All it does differently is put files in an obvious folder instead of saving to the browser’s invisible local storage. This is very intentional. I started down the path of adding things like a real File menu, where you would be able to open story files directly. But it was like tugging a loose thread on a sweater. An Open menu item begs for a Save option too — except Twine 2 constantly saves your work. How would that even work?

(There was a feature request to show an indicator when Twine 2 saves your work, as assurance. What I found was that during any editing, that indicator flickered on nearly constantly. Of course it does it after you stop editing a passage– but it also does it when you drag a passage, or add a new one, and on and on.)

The idea of building a wholly separate desktop, filesystem-oriented Twine 2 in parallel to a web-based one is daunting to me. It would mean a lot of design work, and worse– testing would become a lot harder, and stay difficult. I have automated Selenium tests that exercise the entire web application, and religiously run through them previous to every release. They are annoying to create, but maintaining them is considerably less so. Creating a new set of tests for three separate platforms and keeping them in sync doesn’t seem fun at all.

It’s easy to forget that this would also mean writing a whole other set of documentation, too.

For these reasons, my plan for now is to make the native adaptations for Twine 2 as minimal as possible, so that the Selenium tests resemble the native experience. The native-specific code right now stands at 535 lines long, with four bugs reported against it thus far. (There are probably more, of course.)

I don’t see the online version going away anytime soon. It’s still the best method for people using tablets for now, and despite everything I just wrote, there is still something utterly compelling about being able to go to a web site, click a link, and just write. No password to remember, no terms of service to agree to without reading. A minor form of magic.