# Counter (Example)
This tutorial walks through building a simple counter application to demonstrate VoltX.js fundamentals: reactive state, event handling, computed values, and declarative markup.
## Basic Counter (Declarative)
The simplest way to build a counter is using declarative state and bindings directly in HTML.
Create an HTML file with this structure:
```html
Counter - VoltX.js
0
```
**How it works:**
The `data-volt` attribute marks the root element for mounting. Inside, `data-volt-state` declares initial state as inline JSON.
The framework converts `count` into a reactive signal automatically.
The `data-volt-text` binding displays the current count value. When the signal changes, the text content updates automatically.
The `data-volt-on-click` binding attaches a click handler that increments the count. We call `count.get()` to read the current value and `count.set()` to update it.
Finally, `charge()` discovers all `[data-volt]` elements and mounts them with their declared state.
## Adding Decrement
Extend the counter with both increment and decrement buttons:
```html
0
```
Each button calls `count.set()` with a different expression. The decrement button subtracts 1, while increment adds 1.
## Computed Values
Add derived state using `data-volt-computed` to show whether the count is positive, negative, or zero:
```html
0
Status: zero
```
The `data-volt-computed:status` attribute creates a computed signal named `status`. It uses a ternary expression to classify the count. When `count` changes, `status` recalculates automatically.
## Conditional Rendering
Show different messages based on the count value using conditional bindings:
```html
0
The count is zero
```
The `data-volt-if` binding conditionally renders elements. Only one paragraph displays at a time based on the count value. A reset button sets the count back to zero.
## Styling with Classes
Apply dynamic CSS classes based on state:
```html
```
```html
0
```
The `data-volt-class` binding takes an object where keys are class names and values are conditions. When `count` is positive, the `positive` class applies. When negative, the `negative` class applies. When zero, the `zero` class applies.
## Persisting State
Use the persist plugin to save the count across page reloads:
```html
0
```
The `data-volt-persist:count="localStorage"` binding synchronizes the `count` signal with browser localStorage. When the count changes, it's saved automatically. When the page loads, the saved value is restored.
## Step Counter
Build a counter that increments by a configurable step value:
```html
0
```
The `data-volt-model` binding creates two-way synchronization between the input and the `step` signal. As you type, the step value updates. The increment and decrement buttons use the current step value.
## Bounded Counter
Add minimum and maximum bounds with disabled button states:
```html
0
Range: to
```
The `data-volt-bind:disabled` binding disables buttons when the count reaches the minimum or maximum. The decrement button disables at the minimum, and the increment button disables at the maximum.
## Programmatic Counter
For applications requiring initialization logic or custom functions, use the programmatic API:
```html
```
This approach creates signals explicitly using `signal()` and `computed()`. Functions are defined for event handlers and passed to the scope object. The `mount()` function attaches bindings to the element.
Use programmatic mounting when you need:
- Complex initialization logic
- Integration with external libraries
- Signals shared across multiple components
- Custom validation or transformation
## Summary
This counter demonstrates core VoltX.js concepts:
- Reactive state with signals
- Event handling with `data-volt-on-*`
- Computed values deriving from state
- Conditional rendering with `data-volt-if`
- Two-way form binding with `data-volt-model`
- Attribute binding with `data-volt-bind:*`
- Dynamic classes with `data-volt-class`
- State persistence with plugins
## Further Reading
- [State Management](./state) for advanced signal patterns
- [Bindings](./bindings) for complete binding reference
- [Expressions](./expressions) for template syntax details
- [Lifecycle](./lifecycle) for mount/unmount hooks
- [Server-Side Rendering](./ssr) for hydration strategies