site

  • avoid complexity
  • let content evolve
  • learn by prototyping

to be covered

  • transclusion
  • EIAV (Everything is a View)

breadcrumbs

2026-08-05

nearly all web browsers do a poor job contextualizing individual web pages into their active browsing context. we often follow from one link to another in a complex, elongating, and branching path: this is particularly true if we’re browsing for research or learning (think “going down a rabbit hole”). browsers ultimately collapse the nuances of these traces down to a flat collection of things, relying on the user to keep context alive in their own head.

this complaint is not new, and people have also shared no shortage of concepts and demos attempting to address this challenge. ultimately this is not about browsers anyway. but you should now understand why you’ll see a small trail of breadcrumbs tracking your path when you move from page to page. i see it as a meaningful addition and a way to experiment in the ergonomics and structuring of information (which, in a very true sense, is what this entire site is ultimately about).

SvelteKit provides a robust set of navigation interceptors that allow us to do meaningful work when a user navigates from one page to the next.

beforeNavigate fires before a user is navigated to the next page and exposes an event object which provides us information about the request, like which page they are navigating to and they are navigating from:

beforeNavigate((currentPg) => {
    if (!currentPg.to) return;
    if (currentPg.willUnload) return;
    let toId = currentPg.to.route.id || '';
    let toSlug = currentPg.to.params?.slug || '';
    let fromSlug = currentPg.from?.params?.slug || '';
}

note that it’s possible for some of these to be null, hence the escaping. from.route.id can be null if a user is navigating away from an error page, for example. to avoid issues with navigating away to a different page, we also guard against various cases where subsequent logic may cause issues, like when navigating away to another page.

i’m using a combination of Svelte’s stores and sessionStorage to create and persist breadcrumb information across reloads. if you navigate quickly to another domain and then navigate back to the last page you visited on my site, your breadcrumbs (should) be preserved.

in constructing and modifying our breadcrumb path, we need to recognize that the user might be navigating backward in the trail that they had already established. moreover, with addition of feeds to the site, our logic needs to account for different routing paths (e.g. /feed/* or /entry/*):

routeHistory.update((h) => {
    if (toId == '/') {
        return [];
    } else if (h.some((entry) => entry.includes(toSlug))) {
        return h.slice(
            0,
            h.findIndex((entry) => entry.includes(toSlug))
        );
    } else if (isFeed) {
        return [...h, `/feed/${fromSlug}`];
    } else {
        return [...h, `/entry/${fromSlug}`];
    }
});

we subscribe localStorage to automatically update as changes are made to the path stored in the Svelte routeHistory store.

import { writable } from 'svelte/store';
import { browser } from '$app/environment';

const initialValue = browser && sessionStorage.getItem('storedHistory')
    ? JSON.parse(sessionStorage.getItem('storedHistory')!)
    : [];

export const routeHistory = writable<string[]>(initialValue);

if (browser) {
    routeHistory.subscribe((value) => {
        sessionStorage.setItem('storedHistory', JSON.stringify(value));
    });
}

we need to appropriately clear routeHistory as needed. for example, in the case where a user navigates to another domain but then chooses to navigate back to the home page of the site, we clear out the breadcrumbs so the path does not erroneously display the last session. this is achieved by clearing the trail every time the user visits the main page:

import { routeHistory } from '$lib/stores/navigationHistory';

routeHistory.update(() => {
    return [];
});

over time, i want to be able to potentially provide a means for for people to navigate forward using the same affordance.