npm package: @jondotsoy/location-hash-storage
Description: Manage application state directly in the URL hash with a localStorage-like API. Zero dependencies, reactive updates, and perfect for shareable links and bookmarkable state
Latest version: 0.3.6

# @jondotsoy/location-hash-storage

A lightweight storage solution that manages application state directly in the URL hash (`window.location.hash`). It provides a familiar API inspired by `localStorage` and `sessionStorage`, allowing you to store, retrieve, and reactively observe key-value pairs that persist in the browser's address bar.

## Features

- **Familiar API**: Uses the same interface as `localStorage` and `sessionStorage` (`getItem`, `setItem`, `removeItem`)
- **URL-based persistence**: Data is stored in the URL hash, making it shareable and bookmarkable
- **Reactive updates**: Subscribe to changes with `subscribeItem` for real-time updates
- **Browser navigation support**: Automatically syncs when the hash changes via back/forward buttons
- **Type-safe**: Written in TypeScript with full type definitions
- **Zero dependencies**: Lightweight implementation with no external dependencies
- **SSR-safe**: Gracefully handles server-side rendering environments

## Installation

```bash
npm install @jondotsoy/location-hash-storage
```

```bash
bun add @jondotsoy/location-hash-storage
```

## Usage

### Basic Operations

```typescript
import { LocationHashStorage } from "@jondotsoy/location-hash-storage";

// Set a value
LocationHashStorage.setItem("theme", "dark");
// URL becomes: #theme=dark

// Get a value
const theme = LocationHashStorage.getItem("theme");
console.log(theme); // 'dark'

// Remove a value
LocationHashStorage.removeItem("theme");
// URL becomes: #

// Multiple values
LocationHashStorage.setItem("user", "john");
LocationHashStorage.setItem("lang", "es");
// URL becomes: #user=john&lang=es
```

### Reactive Updates

Subscribe to changes for specific keys:

```typescript
// Subscribe to theme changes (callback called immediately + on changes)
const unsubscribe = LocationHashStorage.subscribeItem("theme", (value) => {
  console.log("Theme is now:", value);
  document.body.className = value || "light";
});

// The callback is called immediately with the current value
// and whenever the hash changes (via setItem, removeItem, or browser navigation)

// Stop listening when no longer needed
unsubscribe();
```

Or listen only to future changes:

```typescript
// Listen to theme changes (callback only called on changes, not immediately)
const unsubscribe = LocationHashStorage.listenItem("theme", (value) => {
  console.log("Theme changed to:", value);
  document.body.className = value || "light";
});

// The callback is only called when the hash changes
// (via setItem, removeItem, or browser navigation)

// Stop listening when no longer needed
unsubscribe();
```

## API

### `LocationHashStorage.getItem(key: string): string | null`

Retrieves the value associated with the given key from the URL hash.

**Returns:** The value as a string, or `null` if the key doesn't exist.

### `LocationHashStorage.setItem(key: string, value: string): void`

Sets the value for the given key in the URL hash.

**Parameters:**

- `key`: The key to store the value under
- `value`: The string value to store

### `LocationHashStorage.removeItem(key: string): void`

Removes the key-value pair from the URL hash.

**Parameters:**

- `key`: The key to remove

### `LocationHashStorage.subscribeItem(key: string, callback: (value: string | null) => void): () => void`

Subscribes to changes for a specific key in the URL hash. The callback is called immediately with the current value and whenever the value changes.

**Parameters:**

- `key`: The key to watch for changes
- `callback`: Function called with the current/new value

**Returns:** An unsubscribe function to stop listening to changes

**Example:**

```typescript
const unsubscribe = LocationHashStorage.subscribeItem("theme", (value) => {
  console.log("Theme changed to:", value);
});

// Later, stop listening
unsubscribe();
```

### `LocationHashStorage.listenItem(key: string, callback: (value: string | null) => void): () => void`

Listens to changes for a specific key in the URL hash. Unlike `subscribeItem`, the callback is **not** called immediately - it only triggers when the value actually changes.

**Parameters:**

- `key`: The key to watch for changes
- `callback`: Function called when the value changes

**Returns:** An unsubscribe function to stop listening to changes

**Example:**

```typescript
// Set initial value
LocationHashStorage.setItem("count", "0");

// Listen for changes (callback won't be called immediately)
const unsubscribe = LocationHashStorage.listenItem("count", (value) => {
  console.log("Count changed to:", value);
});

// This will trigger the callback
LocationHashStorage.setItem("count", "1"); // Logs: "Count changed to: 1"

// Later, stop listening
unsubscribe();
```

## Use Cases

- Sharing application state via URL
- Preserving UI state across page reloads
- Creating shareable links with pre-filled forms
- Implementing simple routing without a router library
- A/B testing with URL parameters

## How It Works

The library reads and writes to `window.location.hash` using the `URLSearchParams` API. It listens to the `hashchange` event to keep the internal state synchronized with browser navigation (back/forward buttons).

## License

MIT © 2025 Jonathan Delgado

## Author

Jonathan Delgado - [hi@jon.soy](mailto:hi@jon.soy)