# How Theme Route Dispatch Works in Hallmark: URL Parsing to DOM Updates

> Discover how Hallmark's theme route dispatch works. It parses URLs, uses localStorage, and applies themes to update the DOM and persist your selection.

- Repository: [Hassan El Mghari/hallmark](https://github.com/Nutlope/hallmark)
- Tags: internals
- Published: 2026-08-15

---

**Hallmark’s theme route dispatch reads the `theme` query parameter, falls back to `localStorage`, defaults to `"hum"`, and executes `applyTheme()` to update the DOM, swap archetypes, and persist the selection.**

The Hallmark project implements a lightweight client-side routing system for theme management entirely within [`site/js/main.js`](https://github.com/Nutlope/hallmark/blob/main/site/js/main.js). Understanding how theme route dispatch works in this repository requires examining the coordinated sequence of URL parsing, state resolution, and DOM synchronization that occurs when a page loads or a user selects a new theme.

## Theme Resolution Strategy

The dispatch process begins with the `initialTheme()` function, which implements a three-tier fallback strategy to determine which theme to activate. This resolution chain ensures themes can be shared via URL while respecting user preferences stored locally.

### URL Query Parameter Detection

On page initialization, the router inspects the current URL for a `theme` parameter using the browser’s native `URLSearchParams` API. The system attempts to extract the value through a wrapped try-catch block to handle malformed URLs gracefully.

```javascript
// From site/js/main.js - initial theme resolution
function initialTheme() {
  const urlTheme = (() => {
    try { return new URL(window.location.href).searchParams.get("theme"); }
    catch (e) { return null; }
  })();
  const stored = localStorage.getItem(STORAGE_KEY);
  return urlTheme || stored || "hum";
}
applyTheme(initialTheme());

```

### localStorage Fallback

If no URL parameter is present, the dispatcher queries `localStorage` using the constant `STORAGE_KEY`, defined as `"hallmark-theme"`. This mechanism allows returning visitors to retain their previously selected theme without requiring URL parameters on every visit.

### Default Theme Assignment

When neither the URL nor `localStorage` provides a valid theme value, the system defaults to `"hum"`. This ensures the application always has a defined theme state, preventing undefined behavior in downstream DOM operations.

## The Dispatch Pipeline: Inside `applyTheme()`

Once `initialTheme()` resolves the target theme, the `applyTheme(theme)` function serves as the central dispatcher that orchestrates all theme-related side effects. This function validates the theme exists within the `THEMES` object before proceeding with mutations.

```javascript
// Core dispatch function from site/js/main.js
function applyTheme(theme) {
  if (!THEMES[theme]) return;
  root.dataset.theme = theme;
  swapArchetypes(theme);
  setPressed(theme);
  try { localStorage.setItem(STORAGE_KEY, theme); } catch (_) {}
}

```

### Updating the DOM Root

The dispatcher immediately updates `root.dataset.theme = theme`, where `root` refers to the document’s root element. This dataset attribute allows CSS selectors to react dynamically to theme changes without requiring class name manipulation or style injection.

### Swapping Archetypes and Copy Fixtures

The call to `swapArchetypes(theme)` replaces the global `ARCHETYPES` mapping and `COPY` fixture objects with theme-specific versions. This architectural pattern enables Hallmark to swap entire component libraries and content blocks based on the selected theme, ensuring consistent visual language across all rendered elements.

### Synchronizing UI State

The `setPressed(theme)` function updates the visual interface to reflect the active selection. This includes modifying the banner label text, updating the genre badge, adjusting footer copy, and toggling the active state on theme selection buttons to provide immediate visual feedback.

### Persistence Layer

Finally, the dispatcher persists the selection via `localStorage.setItem(STORAGE_KEY, theme)`, wrapping the operation in a try-catch block to handle potential storage quota errors or private browsing mode restrictions silently.

## User Interaction Handlers

While the initial page load triggers the dispatch pipeline automatically, user interactions invoke the same `applyTheme()` entry point to maintain consistency. The system listens for click events on elements with the `[data-theme-btn]` attribute, allowing the theme route dispatch to function identically whether triggered by URL or user action.

```javascript
// Event delegation for theme switching
document.querySelectorAll("[data-theme-btn]").forEach(btn => {
  btn.addEventListener("click", () => applyTheme(btn.dataset.themeBtn));
});

```

This design ensures that manually entering `?theme=cobalt` in the address bar produces the exact same state transition as clicking a **Cobalt** button in the UI dropdown.

## Summary

- The `initialTheme()` function in [`site/js/main.js`](https://github.com/Nutlope/hallmark/blob/main/site/js/main.js) implements a three-tier resolution strategy: URL query parameter first, then `localStorage` lookup using `STORAGE_KEY = "hallmark-theme"`, finally defaulting to `"hum"`.
- The `applyTheme()` dispatcher validates themes against the `THEMES` registry, updates `root.dataset.theme` for CSS reactions, swaps component archetypes via `swapArchetypes()`, and synchronizes UI state through `setPressed()`.
- Theme persistence across sessions relies on `localStorage` with robust error handling to prevent crashes in restricted browsing environments.
- Both URL-based navigation and interactive UI elements converge on the single `applyTheme()` entry point, ensuring deterministic state management regardless of the trigger source.

## Frequently Asked Questions

### Where is the theme route dispatch logic located in Hallmark?

All theme route dispatch functionality resides in [`site/js/main.js`](https://github.com/Nutlope/hallmark/blob/main/site/js/main.js) according to the source code analysis. This file contains the `initialTheme()` resolution logic, the `applyTheme()` dispatcher, and all supporting functions including `swapArchetypes()` and `setPressed()`.

### What happens if the URL specifies an invalid theme name?

The `applyTheme()` function includes a guard clause `if (!THEMES[theme]) return;` that silently exits if the requested theme does not exist in the valid themes registry. This prevents the application from entering an undefined state when encountering malformed or non-existent theme parameters.

### How does Hallmark persist theme selection between page reloads?

The system stores the active theme in the browser’s `localStorage` using the key `"hallmark-theme"` (defined as the constant `STORAGE_KEY`). When `initialTheme()` executes on page load, it checks this storage key after checking the URL but before falling back to the default `"hum"` theme.

### Can themes be changed programmatically without user interaction?

Yes, developers can trigger theme changes directly by calling `applyTheme("cobalt")` or any valid theme identifier from the browser console or external scripts. Because the dispatcher updates the DOM, swaps archetypes, and persists to `localStorage` automatically, programmatic calls produce identical results to user-initiated theme switches.