# Global State
VoltX provides built-in global state management through special variables and a globally available store.
These features enable sharing state across components, accessing metadata, and coordinating behavior without external dependencies.
## Overview
Every Volt scope automatically receives special variables (prefixed with `$`) that provide access to:
- **Global Store** - Shared reactive state across all scopes
- **Scope Metadata** - Information about the current reactive context
- **Element References** - Access to pinned DOM elements
- **Utility Functions** - Helper functions for common tasks
## Special Variables
### `$store`
Access globally shared reactive state across all Volt roots.
**Declarative API:**
```html
```
**Programmatic API:**
```typescript
import { registerStore, getStore } from 'voltx.js';
// Register store with signals or raw values
registerStore({
theme: signal('dark'),
count: 0 // Auto-wrapped in signal
});
// Access store
const store = getStore();
store.set('count', 5);
console.log(store.get('count')); // 5
```
**Methods:**
- `$store.get(key)` - Get signal value
- `$store.set(key, value)` - Update signal value
- `$store.has(key)` - Check if key exists
- `$store[key]` - Direct signal access (auto-unwrapped in read contexts)
**Note on Signal Unwrapping:**
When accessing store values via `$store[key]` in read contexts (like `data-volt-text` or `data-volt-if`), the signal is automatically unwrapped. In event handlers, use `.get()` and `.set()` methods for explicit control:
```html
Dark mode active
```
### `$origin`
Reference to the root element of the current reactive scope.
```html
```
### `$scope`
Direct access to the raw scope object containing all signals and context.
```html
```
### `$pins`
Access DOM elements registered with `data-volt-pin`.
```html
```
**Notes:**
- Pins are scoped to their root element
- Each root maintains its own pin registry
- Pins are accessible immediately after registration
### `$pulse(callback)`
Defers callback execution to the next microtask, ensuring DOM updates have completed.
```html
```
**Use Cases:**
- Run code after DOM updates
- Coordinate async operations
- Batch multiple updates
### `$uid(prefix?)`
Generates unique, deterministic IDs within the scope.
```html
```
**Notes:**
- IDs are unique within the scope
- Counter increments on each call
- Different scopes have independent counters
### `$arc(eventName, detail?)`
Dispatches a CustomEvent from the current element.
```html
```
**Event Properties:**
- `bubbles: true` - Event bubbles up the DOM
- `composed: true` - Crosses shadow DOM boundaries
- `cancelable: true` - Can be prevented
- `detail` - Custom data payload
### `$probe(expression, callback)`
Observes a reactive expression and calls a callback when dependencies change.
```html
```
**Parameters:**
- `expression` (string) - Reactive expression to observe
- `callback` (function) - Called with expression value on changes
**Returns:**
- Cleanup function to stop observing
**Example:**
```html
```
## `data-volt-init`
Run initialization code once when an element is mounted.
**Basic Usage:**
```html
```
**Setting Up Observers:**
```html
```
**Accessing Special Variables:**
```html
```
## Global Store Patterns
### Shared Application State
```html
```
### Cross-Component Communication
```html
```
### Persistent Global State
```typescript
import { registerStore, getStore } from 'voltx.js';
import { registerPlugin, persistPlugin } from 'voltx.js';
// Register persist plugin
registerPlugin('persist', persistPlugin);
// Initialize store with persisted values
const saved = localStorage.getItem('app-store');
const initialState = saved ? JSON.parse(saved) : { theme: 'light', user: null };
registerStore(initialState);
// Save on changes
const store = getStore();
const originalSet = store.set.bind(store);
store.set = (key, value) => {
originalSet(key, value);
localStorage.setItem('app-store', JSON.stringify({
theme: store.get('theme'),
user: store.get('user')
}));
};
```
## Best Practices
### Use `$store` for Shared State
Global state should live in `$store`:
```html
Content
```
### Use `$pins` for Element Access
Access DOM elements through pins instead of `querySelector`:
```html
```
### Use `data-volt-init` for Setup
Initialize observers and one-time setup in `data-volt-init`:
```html
```
### Scope Pin Names Appropriately
Use descriptive pin names and avoid collisions:
```html
```
### Clean Up Observers
Always clean up `$probe` observers when no longer needed:
```html
```
## Examples
### Todo App with Global State
```html
```
### Multi-Step Form
```html
```
## API Reference
### `registerStore(state)`
Register global store state programmatically.
```typescript
import { registerStore } from 'voltx.js';
import { signal } from 'voltx.js';
registerStore({
theme: signal('dark'), // Existing signal
count: 0 // Auto-wrapped
});
```
### `getStore()`
Get the global store instance.
```typescript
import { getStore } from 'voltx.js';
const store = getStore();
store.set('theme', 'light');
console.log(store.get('theme')); // 'light'
console.log(store.has('theme')); // true
```
### `getScopeMetadata(scope)`
Get metadata for a scope (advanced use).
```typescript
import { getScopeMetadata } from 'voltx.js';
const metadata = getScopeMetadata(scope);
console.log(metadata.origin); // Root element
console.log(metadata.pins); // Pin registry
console.log(metadata.uidCounter); // Current UID counter
```