Restarting a Twine (not reloading same page) after an idle timeout on a raspberry pi

Twine Version:

Hello. I want to have the story restart if there is no keyboard or mouse action after, say, 2 minutes. I found this code that makes it work great in chrome on my PC, but when I try the file on my Pi4 in Chromium it only reloads the same page of the story and doesn’t restart the story from the beginning:

(function() {

    const idleDurationSecs = 60;    // X number of seconds
    const redirectUrl = location.href;  // Redirect idle users to this URL
    let idleTimeout; // variable to hold the timeout, do not modify

    const resetIdleTimeout = function() {

        // Clears the existing timeout
        if(idleTimeout) clearTimeout(idleTimeout);

        // Set a new idle timeout to load the redirectUrl after idleDurationSecs
        idleTimeout = setTimeout(() => location.href = redirectUrl, idleDurationSecs * 1000);

    // Init on page load

    // Reset the idle timeout on any of the events listed below
    ['click', 'touchstart', 'mousemove','keydown','mousedown'].forEach(evt => 
        document.addEventListener(evt, resetIdleTimeout, false)


I’ve also tried Firefox ES browser on the Pi but with the same result. I want to run it offline on the pi.

Any help much appreciated!


  • I don’t know the specifics of any web-browser that supports a Raspberry Pi device, so I don’t know if those web-browsers behave differently to those that work on Desktop and Mobile devices.
  • Harlowe has been deliberately designed to limit an Author’s ability to use JavaScript to extend the functionality of either their project, or of the story format’s engine itself.
  • Harlowe doesn’t have a documented JavaScript API, so any information about how it works internally needs to be gained by looking at its source code. And any access to the internals of that story format’s engine needs to be done via hacking techniques, like using Scope Escalation to expose those internals.

Harlowe has a (restart:) macro that can be used to programmatically achieve the “Restarting a Twine” effect you mention.

If you look through the source code of Harlowe’s commands.js file for references to restart you will find a couple of reference to the following series of function calls…

if (State.hasSessionStorage) {
	sessionStorage.removeItem("Saved Session");

…which is ultimately what Harlowe does itself to restart a playthrough.

eg. it first uses sessionStorage.removeItem("Saved Session") to get rid of the Session information that is tracking the progress of the current play-through, and then uses window.location.reload() to force the reloading of the HTML file.

So any “monitor idleness” solution you create will need to do the same two steps to cause a “restarting” of the Story HTML file.

Your example is assigning event listeners at the document level for specific events, like “click”, so that the timer of your “idle monitor” can be reset when those event types occur.

But if you look through the source code of Harlowe’s link.js file you will see liberal usage of the <Event>.stopPropagation() method, which stops the triggering event bubbling upwards, so I’m unsure if your current “resetting” technique will work exactly as you want it to.


Thanks so much for your detailed response Greyelf. Sorry, I should have mentioned in my post that I’m pretty much a beginner, so I’m not sure how to put those elements together. Could you spell it out for me really simply, as in, what code you would post where to achieve the effect (disclaimers acknowledged, of course)? Thanks again for your help.

@Greyelf If I’m understanding correctly, I’m trying to do something that Harlowe isn’t really built for. Would it be more straightforward in Sugarcube, do you think? I could always rebuild it if so.

You’re trying to do something that none of the runtime engines of the main Story Formats (except maybe Snowman) are designed to do, because they track Progress History so that they can return the end-user to the current Passage when the web-page is refreshed for whatever reason.

eg. like when a mobile device’s operating system automatically instigates it when the end-user returns to the web-browser app after viewing another app or answering a call / SMS / message.

It may be easier to achieve the behaviour you want using SugarCube, as it doesn’t have the same JavaScript limitations as Harlowe and it has a documented API, but you would still need to clear out its Progress History to stop the current Passage being returned to upon page refresh.


I see. Many thanks, Greyelf!