Loading content...
"For a thing whose presence or absence makes no visible difference, difference is not an organic part of the whole."—Aristotle, Poetics
Recently, an agency I worked with ages ago—I'm not saying which one—rebranded its website. Visiting it, I entered a landscape of functionalism without connected parts. The parts did their job; for example, the contact section allowed you to press send, the portfolio section contained static images that refused to respond to any interaction, team photos moved up on scroll, and some info boxes moved left to right when entering view.
To the agency's defense, this is rather commonplace on the web. Often, developers, and sometimes designers, focus on the question, "Does this unit work?" A login button, a database query, or a loading spinner represents an independent task to be completed. Each task is a test, and upon completion, the task is checked off the Kanban board.
In this view, the code is just an engine, and the design its paint. This might not even be a "view"; it is just how things evolve as things need to get out the door and online. I especially see this pattern when management writes the code—no, trust me, forget flat structure, I've seen it happen.
But this approach usually creates a fragmented experience—a heap of features rather than a cohesive whole, an archaic form of template; as archaic as FrontPage once was to Flash. It narrows our spectrum down to the belief that code itself cannot benefit from a narrative approach.
Oh well, it is the living penguin right now, that code can!
Code as a narrative
In his work Poetics, Aristotle described the concept of narrative reasoning, arguing that a great story isn't just a sequence of events; rather, it is a structural union so tightly knit that displacing a single part disjoints and disturbs the whole. He famously noted that "a thing whose presence or absence makes no visible difference is not an organic part of the whole."
In the world of code (and design), this can be interpreted to mean that our atoms are not just technical chores but the very heartbeat of the user journey. When the code stutters, the narrative breaks; when the state is inconsistent, the app develops amnesia, and the user is pulled out of the experience.
Here's an image that vaguely illustrates what I'm after:
Let's step through that illustration.
Memory
Problem
A user returns to the application and tries to change previous selections by pressing the browser's back button. However, instead of returning to their original position, they land at the very top of the page, leaving their selections hidden and out of view at the bottom. This breakdown in Scroll Restoration—the browser's ability to remember a vertical scroll position—disrupts the user experience and creates a glitch in the narrative flow.
Solution
To maintain a seamless narrative, the application must ensure that the scroll position is accurately restored. For example, in Vue, using Vue Router's scrollBehavior, the app automatically captures and restores the user's saved scroll coordinates, ensuring they return to where they left off instead of jumping back to the top.This keeps their selections immediately visible, preserving the rhythm of the story and preventing a jarring return to the top of the page.
State
Problem
In a customizable dashboard, a user's layout and widget states—such as coordinates and collapsed positions—are often lost when the session ends or the browser is closed. Without a way to preserve these configurations, the user is forced to rebuild their workspace from scratch every time they return. This creates a disjointed experience, making the application feel like a temporary tool rather than a reliable, persistent workspace.
Solution
By utilizing Pinia to track widget coordinates and states, and integrating a localStorage plugin, we ensure the data persists across sessions. The dashboard becomes a narrative: the widget becomes fixture of the user's environment. When the user returns even a week later, the layout remains as it was left, maintaining the continuity of their workspace.
Latency
Problem
Waiting for a promise to resolve before updating the UI is another classic anti-narrative. When a user clicks a button and nothing happens for several seconds, the application's flow stops. This creates a jagged rhythm where content suddenly pops in without warning, leaving the user in a state of uncertainty or, worse, driving them to abandon the page for a cup of coffee while waiting for a large data fetch to complete (albeit coffee is a good thing).
Solution
To maintain the application's narrative beat, we must account for the loading phase. Instead of blocking the view, we can use Svelte's built-in {#await} block, which forces us to provide a fallback or loading state, ensuring the user receives immediate feedback. By treating the transition as part of the experience, rather than a delay, we preserve the application's rhythm and keep the user engaged while the data fetches in the background.
async function loadChapter() {
return fetch('/api/chapter-2').then(r => r.json());
}
function handleClick() {
promise = loadChapter();
}
</script>
<button on:click={handleClick}>Next Chapter</button>
{#await promise}
<p>The story continues...</p>
{:then data}
<p>{data.content}</p>
{/await}
</script>
Syntax
Problem
Traditional form handling often relies on a submit gatekeeper, creating a disjointed experience between a user's input and the application's response. This approach forces a static, chore-like interaction where the user must finish a task before seeing any result. Without an immediate feedback loop, the dialogue between the user and the interface breaks down, making the application feel reactive only on demand.
Solution
Another Vue solution, although any framework or vanilla JavaScript will do! By using Vue's v-model directive, we keep the interaction in the present tense, creating an unbroken dialogue between the user and the application. This removes the awkward pause of a submit button, turning a static form into a live conversation. As the UI binds directly to the state, the application acknowledges the user's existence with every keystroke. The code stops being a series of chores and becomes a mirror, reflecting the user's actions in real time:
<script setup>
import { ref } from 'vue'
// This is the "Memory" or the "File"
const username = ref('')
</script>
<template>
<!-- The Input (The User's Action) -->
<input v-model="username" placeholder="Type your name...">
<!-- The Narrative (The Instant Response) -->
<h1>Welcome, {{ username || 'Stranger' }}!</h1>
</template>
Narrative union
Consider live search as the heartbeat of this narrative: when a user types, the syntax of a v-model instantly updates the global state, which in turn triggers a latency strategy—like a skeleton screen—that holds the physical space for the incoming data. Because the story is unified, the memory of that search term is automatically anchored to the browser's history. When the user eventually hits the back button, they aren't met with a blank page or a reset form; they are returned to the ave point of their journey.
In the design phase, this narrative represents the transition from a collection of static frames to a spatial logic. In a tool like Figma, it's easy to design a contact page and a portfolio page as two separate islands, but a narrative-driven design treats them as different views of the same constant environment.
The sites that win awards aren't just pretty; they are narratively consistent, treating the user's journey as a single, unbroken line of code and design. Often, they speak a daring language, far removed from the functionalism of forty different buttons shouting for attention.
From the halls of CSS Design Awards, here are three examples of narrative unity that rock my world
Thank you. Now go to the sea, breath some fresh air, and remain still.
Notes
Aristotle. Poetics. Translated by S. H. Butcher, The Internet Classics Archive, 2009, https://classics.mit.edu/Aristotle/poetics.htmlClarke, Justin. "Code as a Story: Unveiling the Narrative Essence of Programming." Medium, 5 Sept. 2023, https://medium.com/@justin.ce.inc/code-as-a-story-unveiling-the-narrative-essence-of-programming-8fa89e9a131c
Weigel, Martin. "Reconciling the Tension Between Code and Story." Martin Weigel, 7 June 2011, https://www.martinweigel.org/mrweigelgmailcom/2011/06/07/code-and-story