A window is denoted by a pair of parentheses that contains two or more choices within, delimited by a vertical bar, or pipe. In the line this is (my|your|our), there are three choices: “my”, “your”, and “our”. The choices can be multi-word strings containing spaces (but not line breaks), such as (Sentenced Faces|Foundering Faces), which are the two choices “Sentenced Faces” and “Foundering Faces”. You can also include an empty choice. For example: my dream job is (poet|artist|astronaut| ), which breaks out into “poet”, “artist”, “astronaut”, and an empty choice denoted by the space.

The default choice, or the one that you see before you begin interacting with it, is the first item given in the list.


You can also link windows so they move together. To do so, add a number in square brackets after each window.

this is (my|your|our)[1]
for (this moment|forever)[2]

In this poem, all windows tagged with [1] will move together, while all windows tagged with [2] will move together.


By default, windows move vertically (north–south), but you can specify a horizontal (east–west) direction by including a hyphen in square brackets.

This will move vertically:


while this will move horizontally:


This can be combined with linking, but the order matters: it’ll look for the link first, then the hyphen. This will incorporate nicely:


while this will not:


Custom functions

Choices can be linked to custom functions (defined by you) to be called when that choice is activated. In the line below, there are two choices, each linked to a different custom function.

in the (mist->turnGrey|missed->turnBlue)

In your code, you might create a function named turnGrey(), which sets the page background to grey, and a function named turnBlue(). which sets the page background to blue.

function turnGrey() {

function turnBlue() {

The functions can be passed into the ProsePlay object using setFunction().

pp.setFunction("turnGrey", turnGrey);
pp.setFunction("turnBlue", turnBlue);

With these functions set, selecting the mist choice will automatically call the turnGrey() function, and selecting the missed choice will automatically call the turnBlue() function.


To escape a window (i.e. to leave it as text and not make it interactive), insert a backslash before the opening parentheses. For example, to escape the window in the string this is (my|your|our), write this is \(my|your|our).

Using ProsePlay as a library

You might be interested in using ProsePlay as a library on your own site so you can host your poem, integrate it into a larger project, and/or add your own styles and scripts to it.

ProsePlay is available to install from npm.

npm install proseplay

In your project, import the library.

import { ProsePlay } from "proseplay";

The fastest way to see what this library does is to load up a sample text.


Opening your webpage, you should be able to see an interactive poem.

Let's try it with our own creations!

Note: There are two main approaches to calling ProsePlay—the static method and the non-static method. These examples will focus on the static methods for brevity, but the non-static methods are given in comments in case you want to control where the poem goes on the page.

const poem = `this is (my|your|our)
very (lovely|cool|weird)

// // non-static
// const container = document.querySelector(".text");
// const pp = new ProsePlay(container);
// pp.parse(poem);

Opening the page, you should see the result of ProsePlay parsing the string.

You can now add your own CSS styles to position and shape the container, as well as change things like font family, font size, and color. Beyond those properties, it may take some trial and error to get the intended effects.

You can also have multiple ProsePlay poems running on the page, like this:

const poem1 = `this is (my|your|our)
const poem2 = `let us (read|write|play)`;

// // non-static
// const poems = [poem1, poem2];
// const containers = document.querySelectorAll(".text");
// containers.forEach((container, i) => {
//   const pp = new ProsePlay(container);
//   pp.parse(poems[i]);
// });