I’ve been diving into the code of the Twine Web App. It’s something I’ve wanted to do for a while, especially since the Twine Web App can be hosted from nearly any web server. In fact, I’ve already propped up a copy on one of my domains (please note this version has been altered from its original format). My goals for this project involved customizing a version of Twine to better support instructors who participate in my Twine professional development curriculum. All that to say, this post is to help me document my thinking and share my ideas as I explore.
Before I dive in, be aware that I’m NOT a traditional coder. I’m just an educator who likes to tinker with tech and have no formal computer science training. For example, I haven’t been messing with the source code files of Twine, instead I’ve been modifying the already compiled web app files as they’re much more accessible for me and my current knowledge level. Alright, disclaimer complete, let’s take the plunge!
Learning To Customize
After downloading the Twine Web App, I opened the code in Atom to view the rather large twine.css and twine.js files. Working with these files, was difficult since they mostly contained walls of text that made it complicated to discern any code:
Therefore, I had to work backwards from the web app to find the appropriate pieces of code to alter. First, I opened the Twine Web App index.html file in Chrome and used the web inspector feature to view the individual code elements of the App. This allowed me to search for particular phrases in the code to determine where I could make changes. For example, I looked at the sidebar menu of Twine to see what elements existed there and this gave me some ideas about what I could modify—the “listControls” for example:
Adding An Image To The Menu
In the twine.js file I found this string (notice that it contains “listControls” which is what I searched for using Atom):
<nav class=listControls><h1 class=logo>{{ ‘Twine’ | say }}</h1> <ul class=plain>
Modifying this code, I was able to add some text (“Edition”) to the right side menu:
<nav class=listControls><h1 class=logo>{{ ‘Twine’ | say }}</h1> <div><h2>Edition</h2></div> <ul class=plain>
However, I wanted to determine how the Twine logo appeared in this sidebar since I didn’t see any indication of images within this part of twine.js. In fact, I was extremely curious how “h1 class=logo” was also pulling in an image at all. Turns out after searching “h1{” in the twine.css file, I found that the Twine logo was loaded as a background image from this CSS code:
#storyListView nav.listControls h1{margin:0;padding-top:3em;background:top no-repeat url(…);background-size:50%}
So, I cloned this code and made tiny alterations to load one of my own images:
#storyListView nav.listControls h2{margin:0;padding-top:4em;background:top no-repeat url(rsrc/xp-icon.png);background-size:50%}
These modifications yielded the following Twine Web App menu:
Embedding Links In Menu
Since I added the above image through CSS, I was unsure how to use a hyperlink with this image. I tried a myriad of things in both twine.js and twine.css to no avail. Eventually I decided to take a different approach and add links to another menu already present in the Twine Web App sidebar.
Searching for “Help” (one of the Twine sidebar items) using Atom, I stumbled upon this code:
<li> <button class=block @click=showHelp title=\”{{‘Browse online help’ | say }}\”> <i class=\”fa fa-question-circle\”></i> {{ ‘Help’ | say }} </button> </li>
But this part of the javascript file didn’t contain a hyperlink. I figured the “@click=showHelp” was important and searching for “showHelp” using Atom yielded the following function (bingo! this is how I’ll create a hyperlink):
showHelp:function(){window.open(“https://twinery.org/2guide”)}
SO, I learned that I needed to create a function AND generate a <li> element to accomplish my goal. These are the two pieces of code I wrote into the twine.js file (right in front of the respective codes I found):
<li> <button class=block @click=showTwineedu title=\”{{‘See Education Resources’ | say }}\”> <i class=\”fa fa-paperclip\”></i> {{ ‘Edu Resources’ | say }} </button> </li>
and
showTwineedu:function(){window.open(“http://twinery.org/wiki/twine:education”)},
Notice in the <li> code block that I used “fa-paperclip” (etc.) to bring in icons from Font Awesome for my menu items. The results of these modifications looked great:
For now, I’m done with my alterations and you’re welcome to compare my modified version of Twine versus the original.
Adding Value Through Customizations
Looking forward, there are more modifications that I’d like to add to Twine—here are a few:
1) Example story/game already loaded into the Twine Web App for folks to experiment with. Since I often use Twine with beginners, if I could load tutorial materials and example stories/games automatically into everyones saved stories section this would be ideal. It would be an excellent way to encourage people to look “under-the-hood” at how stories are constructed in Twine and how basic coding can be used to enhance the appearance and experience of a story/game.
2) (Alternatively) Saved files be hosted on the web server versus the web browser cache. One of the features of the Twine Web App, is that people’s stories/games are saved to their browser cache. Adding the option to save games directly on the web server where the Twine Web App was operating would be a great alternative that could also solve #1 because all games on the web server could then be accessible to all the visitors. This customization would be a great option for learners to explore each others projects and stories/games that are curated by instructors.
For privacy’s sake, I wouldn’t recommend building personal stories/game in this customized web app if this feature was implemented—only use it as a learning tool. Twine stories can be quite personal and private and I’d recommend using the regular web or desktop versions of Twine for such projects. For instance, I wouldn’t have felt comfortable publicly displaying the development of Healing Words.
3) “Publish to File” with automatic hosting option. When faculty participate in eXperience Play (XP), we cover publishing Twine stories/games. Some instructors want us to host their stories/games from the XP website and it would be excellent if games built in this customized version of Twine could be automatically submitted to us. That would eliminate some logistics if folks could push a button and automatically publish to philame.la or our collection of games.
4) “Publish to File” as a Canvas submission. I’ve already been testing the viability of Twine inside of Canvas (see images below). It would be cool if an LTI integration could be used to streamline the process for students to submit their stories to their instructors for feedback. Whether this occurred through Twine or if a Twine-Canvas LTI could access and read the browser cache to view and submit saved story/game files—that would be slick!
Closing
I’m excited this learning exercise got me thinking about different ways to enhance (open) applications that I’m using. More than that, wrestling with Twine’s code made me appreciate this software even more. I’m so thankful to Chris Klimas and everyone else who works on Twine as it’s become a special piece of software in my life. Not only has Twine helped me overcome the loss of a loved one, but its open and inviting nature has encourage and challenged me to tackle coding exercises I’ve not felt comfortable pursing in the past. So thank you Twine for helping me grow and pushing me to learn more!