About that Patreon fee change…

This post originally appeared on my Patreon.

I didn’t understand the significance of the email I received from Patreon about fee changes at first. It was written in that shallowly friendly tone that customer-facing tech companies have nearly universally adopted as their style guide, that regardless of its actual content aims to disarm you. It took until I read Jimmy Maher’s explanation that I saw what was afoot. It’s a one-two punch.

First, patrons will pay the transaction fees for their pledges instead of the burden being shared between myself and Patreon. I can see arguments both for and against making this change. Personally, I always looked at the fees as the cost of doing business here. I certainly wasn’t losing sleep over them.

Second, patrons will be charged fees on each individual pledge, not on every credit card charge. These fees no longer have a direct connection to payment processing fees. They’re essentially Patreon turning up the revenue knob.

Patrons who spread their pledges wide-but-thin will feel the pain the most. About 60% of my patrons pledge $1. Already, I have seen one person cancelling their pledge. I wonder how many others will do so once the change goes into effect on the 18th.

I am not sure what I’m going to do. Right now, I am considering my options carefully. I had actually been thinking of adding reward tiers to this Patreon, and had been brainstorming what those could be in the context of open-source development. But now I am not sure where this will end up. I want you to know that I’m thinking about it, however, and I would like to hear your thoughts on the change in the comments. Am I overreacting? Should I think about changing something about my Patreon?

I’ll close with a thank-you to everyone who has supported my work on Twine, whether it’s been with money, an appreciative tweet or comment, or a contribution of code or documentation. What I find most gratifying about Twine is the impact it has had and continues to have. I am so happy that so many of you have made wonderful things with it.

Edit: Natalie Luhrs has posted a deep dive on the numbers involved.

Observations on Mosaic

After trying out Steven Soderbergh’s interactive movie Mosaic, I was surprised to find that there are very few reviews of it online, only puff pieces promoting it before it was released. So, some observations.

First, although nearly every piece in the press describes it as in the vein of Choose Your Own Adventure, Mosaic is not a CYOA. It’s a movie that allows you to leap between points of view as you move through the story, with additional segments and background documents revealed as you progress. You can move backwards chronologically as much as you’d like, but you may only plod forward in time– so as not to spoil the surprises of the story, I would guess.

Another way to look at it: if Mosaic was a written work, we’d comfortably call it hypertext. I think the reason for the Choose Your Own Adventure comparison is that it’s the one thing the mainstream press understands is a form of narrative that requires reader participation to progress– that isn’t a video game, anyhow. I suspect no one is brave enough to compare Mosaic to a video game to Soderbergh’s face.

I don’t understand exactly why, but Mosaic is being released as both interactive app (on iOS) and linear TV series (on HBO). It seems extraordinarily challenging to design a narrative that will work in both contexts, and perhaps that’s why despite Mosaic holding my interest as I watched it, I came away a little disappointed. As I watched the final scenes (unlike many hypertexts, there really is a dénouement), I thought: “I guess we are wrapping it up here?”

I believe I am paraphrasing someone, though I can’t exactly place who right now, when I write that the two main problems hypertext readers have to grapple with are:

  1. Where am I in the story?
  2. Am I done reading?

So as a debut work of interactive narrative, it is not surprising that Mosaic ran headlong into problem #2. Mosaic‘s ending is a bit Chinatown, so part of it was that I felt emotionally unsatisfied–but more than that, I wished that there was more there there. The digressions provide more explanation behind some of the actions of the characters, but they felt like browsing the appendices of a book, and not the cool kind of appendices. You also don’t have to do anything to unlock the extra video segments, so there isn’t much of a thrill of discovery. Maybe if Mosaic didn’t wrap up all the loose ends I saw, left some mystery for me to untangle, I would’ve found the extra material more engaging.

The story itself? Interesting in parts, cliché in others. I found Joel’s segments the most interesting, but I hesitated a bit even there. He’s depicted as suffering from mental illness, and though I am far from an expert on these things, as I spent more time in his perspective it began to feel like a cartoony, larger-than-life version of mental illness. He also commits nearly every clichéd action a person in his position should never do. You’ll understand what I mean when you get there.

I think the most daring part of Mosaic is that most video segments are 20 minutes or longer–which sounds like damning with faint praise, doesn’t it? But I think it worked. It gave me space to get comfortable and slip into a reflective state of mind instead of an active one (the kind you need to play, say– a video game).

Mosaic also requires you to set up an account to experience it, but all it’s ever done with it is email me a few days after I finished the storyline to remind me, a little pedantically, that there was to more look at. I opened the app again, but nothing seemed different–it was just a stack of videos that would elaborate on, but not transform what I had already seen.

p.s. It is always sort of funny to see James Ransone onscreen. He and I went to high school together–he was a friend-of-a-friend–so I have a strange, asymmetrical familiarity with his face.

I’ll be at WordPlay 2017

Next weekend, I’ll be speaking at WordPlay in Toronto, as well as giving a Twine workshop there. The workshop will be a little bit of an experiment; in the past, I’ve done workshops using the default Twine 2 format, Harlowe, but for this one I’m going to try showing people Snowman. What I have found with Harlowe is that eventually people will ask about some edge case that I don’t have a great answer for, but I totally know how I would do it with Snowman–so I’m going to see if I can get people up to speed with Snowman. Hopefully, it will not be too steep of a climb for an hour-long workshop. We’ll see!

It will be my first time at WordPlay and my first time in Toronto, and I’m excited about both! Though I am not excited about the cold. It has been unseasonably warm here until this past week, so I held out hope that Toronto would be not supercold. It’s looking like I will not be so lucky, however…

Twine 2.2.0 beta 1

This post originally appeared on my Patreon.

It’s been a while but hopefully this will be a nice surprise– with the caveat that it’s a beta, and so I wouldn’t use it with your most important story of all time that’s due tomorrow morning. You can get it on Bitbucket.

What’s new?

  • Passages can now be wide, tall, or just plain large. Make important passages bigger on the map so they’re easier to find.
  • Tags can be assigned colors, which show up as a vertical stripe on a passage in the story map. Every tag doesn’t need to have a color–it’s up to you.
  • You can now press the plus and minus keys to change the zoom level of the story map.
  • A Turkish localization has been added thanks to H. Utku Maden.

Here’s what’s fixed:

  • When you zoom in and out, Twine does a better job of keeping the window centered where you were looking.
  • The zoom level you last set for a story is now remembered by Twine.
  • If for some reason a story format can’t be loaded, you can still delete it.
  • The desktop app is more tolerant of story files that it has trouble importing at startup — it keeps going, so you at least can get to the story list.
  • If the desktop app does run into problems on startup, it shows the error message it should. For a little while, it would show just a white window… not very helpful.
  • A bunch of libraries that aren’t needed anymore have been removed, so the web version’s size is a bit smaller!


Twinery.org has changed servers

I was alerted by M.C. DeMarco on Sunday to an issue with twinery.org. Namely, the home page was serving up malware in one of its JavaScript files– the little script that shows the screenshots at full size when you select a thumbnail. That’s pretty bad. (To be honest, I am not sure of all the bad things that malware may have done. You can examine a copy of it on the Wayback Machine. What I saw it do was, after I clicked a link on the home page, pop open an ad under my browser window.)

After investigating things, a number of other things accelerated things from pretty bad to intensely bad:

  • Judging from the Wayback Machine, the twinery.org home page began serving malware sometime in July of this year.
  • I could not determine exactly how the malware got on the site in the first place. My best guess currently is that I didn’t update one of the software packages on the site in a timely enough fashion and someone took advantage of that, but I don’t know for sure, and I don’t know how to be sure.

The one silver lining was that the issue appeared to be contained to just the home page. The online Twine editor, in particular, was untouched. The downloadable versions of Twine 2 are hosted at Bitbucket.org, so those were not in any danger, and I’ve run virus scans on the Twine 1 installers hosted on the site, which have come up clean.

I deleted the malware that same day, but given that someone had the ability to edit files at will on the web site for several months, stronger measures were called for. Conventional wisdom holds that the only way to be sure that there were no nasty surprises in store was to rebuild the server from trusted sources.

This caused some plans I had been making to accelerate. For the past several months, I’ve been discussing the possibility of moving twinery.org to an Interactive Fiction Technology Foundation server with the rest of the IFTF board (I am also a member). Up until now, the web site had been hosted on Dreamhost shared hosting. Dreamhost has been generally great–in particular, I am a fan of how easy they make it to enable Let’s Encrypt on a web site–but occasionally the site would go down for 15 minutes or so, and the best answer customer support could give me was that it was consuming too many resources and had been shut off temporarily.

So, I reasoned, if I’m going to rebuild the server, I may as well do it once, not twice. Tonight, we switched twinery.org from Dreamhost to a server that IFTF operates.

It has, unfortunately, not been a completely smooth transition. We weren’t yet prepared to migrate the active email addresses on twinery.org (I have a couple for administrative purposes). In order to make this kind of halfway change, I had to first turn off the Dreamhost site hosting, then point the domain name to the new server in Dreamhost’s control panel.

The upshot of this is that for a while, you may see twinery.org displaying a cute Dreamhost robot that’s fallen over. Hopefully the change will propagate quickly, but if it hasn’t, your patience is appreciated. I wasn’t expecting this to happen–I thought the cutover would be seamless–but I hope this won’t cause too many problems for anyone.

If you do see other issues with the web site, please drop a line to @twinethreads. I usually check in on that account at least once a day.

Collaborative Twine

Ross Ramsay, one of my Patreon supporters, asked:

I was just curious if you had any plans to incorporate Dropbox or some way to synchronize and collaborate with the program? If you eventually add some kind of mobile system for this, it would be almost needed to sync between devices. As is, I’d use it to work with others, and sync between my work and home computer. With the ability to sync in some way, you might be able to use the mobile platform instead of having a dedicated mobile version for iOS and Android.

One great weakness of Twine is that it has no real way to collaborate with other authors. When I originally created Twine as a desktop app, sharing a Twine story meant sharing the file through whatever means at hand– email, a network share, Dropbox, what have-you.

Technically speaking, this option remains in the Twine 2 era. But in the era of Google Docs and Office 365, expectations have changed. Not only do people not want to mess around with file sharing — the expectation is that data lives in the cloud, which is to say “someone else’s server” — but there’s also an expectation that multiple people should be able to edit simultaneously. These are not unfair expectations to have! In particular, the idea of simultaneous editing just makes sense. But they impose additional levels of complexity on an application.

(It reminds me of the shift from modal, text-based applications to event-driven GUI apps. I am not old enough to have actually worked on an app back then, but I remember reading about this in programming books I devoured as a kid. In both cases, a fundamental change in perspective was required.)

I decided very early on in the Twine 2 design process that I did not want to be responsible for storing stories on a server I controlled. I’ve seen other systems — and continue to see new ones crop up — that do this, and when this happens, authors become captive audiences of those who run the servers. Without some kind of financial means to keep the lights on, these services only exist so long as their maintainers have interest — and in most cases, that can be measured in years, sometimes months. Imagine writing a story that just disappeared five years later! It would be a strange, even outrageous idea in the physical world. And yet we accept such ideas without much more than a sigh when they occur online.

There were other concerns to running a centralized Twine server, too. I believe that as long as you house content, you share responsibility for it — though this does not seem to be an attitude that everyone shares these days. I’m speaking here in moral terms, not really legal ones. I understand what safe harbor provisions are. Policing content for odious stuff like racism, pedophilia, and so on is not something I want to do. It’s a thankless but necessary job.

I also looked into integrating with services like Dropbox, but in my limited exploration, I found that they expected you to have your own server backend that will talk to their services, not have clients speak directly to them. Twine 2 doesn’t have a backend. In this respect, it still resembles its TiddlyWiki parentage. An important cavest — my understanding of this might be outdated. It’s been some time since I did that exploration.

In short, I would very much like to work on a collaborative Twine server but I don’t have the time or resources to do so right now. And before I started working on it, I’d need a real plan for sustainability that I was confident in. It would only be fair to people using it.

That said, I consider this subject an open question, not a sad conclusion.

Twine 2.1.3

This originally appeared on my Patreon.

This fixes a bad bug with 2.1.2 that could cause stories to become corrupted, so if you have downloaded 2.1.2, please upgrade to this as soon as you can.

This seems like a reasonable time to talk about how testing with Twine works. Initially, the test suite used a tool called Selenium that scripted actions in a web browser and verified the results. The problem with this approach is that it has turned out to be both brittle and flaky. Brittle because I would make a change to a small part of the code and 5 tests would break sometimes, and flaky because there were often difficult-to-debug timing issues with the tests that would cause them to succeed some of the time, and not others — on the same code. Not ideal.

(I know there are lots of happy users of Selenium, to which I say: good on you. But it hasn’t been good to me.)

With the Twine 2.1 series, I’ve been focusing on unit testing, which isolates each part of the code and tests each bit of it individually. It’s been a lot more reliable thus far, but it takes time to write all the tests. I’ve been focusing unit tests on the data layer, because bugs that cause data corruption are the worst in the world. They trash users’ work and leave me feeling horribly guilty. I’m the dog that ate your homework.

The bug that was in 2.1.2 didn’t have any testing associated with it. It was a sin of omission: if a grid spacing wasn’t specified when snapping passages to the grid, passages that are automatically created as you edit your story (e.g. when you type [[A link]]) would be assigned nonsense coordinates onscreen (NaN, if you speak JavaScript), which firstly caused them to not be displayed, and secondly could cause other passages to get their coordinates trashed, as Twine tries to keep passages from overlapping each other.

(No, there isn’t any way for an end user to change grid spacing, because it’s always felt unnecessary to me… but it’s always good to leave ourselves that option should we want it someday.)

Now the offending code has checks for grid spacing, and there is a specific test to check that it handles those situations correctly. So it shouldn’t happen again. Let’s hope. There is always a degree of uncertainty with software engineering.

Twine 2.1.2

This was originally posted to my Patreon.

It’s out now! You can download it from the main site ; I’ve also posted release notes  to the wiki. This release should fix a nasty bug affecting non-English speakers and also clean up some issues related to story format versions.

The localization issue was particularly insidious. What was happening was:

1. The app would do its initial startup and load in stories from the Twine/Stories directory, creating it if needed. This step would ask the localization code to translate the name “Stories”, but because localization data hadn’t been loaded yet, it would fall back to translating it to “Stories”, no matter what langauge you wanted to use.

(The reason for this fallback is so that if something gets really messed up, you can still at least get some words on the screen, even if they’re in a language you don’t speak.)

2. The rest of the app initialization would occur, including loading localization data.

3. A user would make a change and Twine would try to save it to that Twine/Stories directory… only this time, it would translate the folder name. So if you speak French, for example, it would try to save to a nonexistent Twine/Histoires directory and fail.

The solution was simple — load the localization data as early as possible — but it was tricky to diagnose.

Looking at the release notes page tonight, I realized the last release was about three months ago. I think we’re on that pace, roughly, for future releases as well — perhaps a little bit faster.

I’m also working on Snowman 2.0 and am close to a release on that, which is exciting. It’s not too too different, but I am changing some syntax, most notably the way you create <div>s and <span>s (which is buggy in the 1.x series).

The middle beast, a tremor of trepidation in his words, said, “You aren’t from a dark planet, are you?”

“No.” Calvin shook his head firmly, though the beast couldn’t se him. “We’re–we’re shadowed. But we’re fighting the shadow.”

(Madeleine L’Engle, A Wrinkle in Time)