Documentation
Everything you need to get started with genX.
Installation
Choose the installation method that works best for your project.
Option 1: CDN (Recommended)
The fastest way to get started. Add this script tag to your HTML:
<script src="https://cdn.genx.software/v1/bootloader.js" defer></script>
The defer attribute ensures the script runs after the DOM is ready.
Option 2: Self-Hosted
Download and host the files yourself for full control:
# Clone the repository
git clone https://github.com/adamzwasserman/genX.git
# Copy source files to your project
cp genX/src/*.js your-project/static/js/
Then reference the bootloader in your HTML:
<script src="/static/js/bootloader.js" defer></script>
Option 3: npm (Coming Soon)
npm install @genx/core
Quick Start
Once installed, you can immediately use genX attributes in your HTML:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>My Page</title>
<script src="https://cdn.genx.software/v1/bootloader.js" defer></script>
</head>
<body>
<!-- Currency formatting -->
<p>Price: <span fx-format="currency">99.99</span></p>
<!-- Phone number formatting -->
<p>Call us: <span fx-format="phone">5551234567</span></p>
<!-- Date formatting -->
<p>Published: <span fx-format="date" fx-date-format="long">2024-03-15</span></p>
</body>
</html>
How It Works
genX uses a lightweight bootloader that:
- Scans your page for genX attributes when the DOM is ready
- Detects which modules are needed based on attribute prefixes
- Loads only the required modules on-demand
- Processes elements with the appropriate module
- Watches for dynamic content via a centralized MutationObserver (powered by domx)
This means you only pay for what you use. If your page only uses fx-* attributes, only the fmtX module is loaded.
Architecture note: genX uses a single shared MutationObserver for all modules through domx-bridge, eliminating duplication and improving performance compared to per-module observers.
fmtX — Formatting
Prefix: fx-*
Format text, numbers, dates, and phone numbers with simple attributes.
Currency
<span fx-format="currency">1299.99</span>
<!-- Output: $1,299.99 -->
<span fx-format="currency" fx-currency="EUR">1299.99</span>
<!-- Output: €1,299.99 -->
<span fx-format="currency" fx-currency="JPY">1299</span>
<!-- Output: ¥1,299 -->
Phone Numbers
<span fx-format="phone">5551234567</span>
<!-- Output: (555) 123-4567 -->
<span fx-format="phone" fx-phone-format="intl">15551234567</span>
<!-- Output: +1 555 123 4567 -->
Dates
<span fx-format="date">2024-03-15</span>
<!-- Output: 3/15/2024 -->
<span fx-format="date" fx-date-format="long">2024-03-15</span>
<!-- Output: March 15, 2024 -->
<span fx-format="date" fx-date-format="relative">2024-03-15</span>
<!-- Output: 2 days ago -->
Numbers
<span fx-format="number">1234567</span>
<!-- Output: 1,234,567 -->
<span fx-format="number" fx-decimals="2">1234.5</span>
<!-- Output: 1,234.50 -->
<span fx-format="percent">0.156</span>
<!-- Output: 15.6% -->
accX — Accessibility
Prefix: ax-*
Enhance accessibility with ARIA attributes and keyboard navigation.
<!-- Accessible button with label -->
<button ax-label="Close dialog">×</button>
<!-- Accessible image -->
<img src="chart.png" ax-desc="Sales chart showing 20% growth">
<!-- Skip to main content link -->
<a href="#main" ax-skip-link>Skip to content</a>
<!-- Live region for dynamic updates -->
<div ax-live="polite">3 items in cart</div>
loadX — Loading States
Prefix: lx-*
Add loading indicators, skeletons, and progress states.
<!-- Loading spinner -->
<button lx-loading="true">Submit</button>
<!-- Skeleton loading -->
<div lx-skeleton="text">Loading content...</div>
<div lx-skeleton="card"></div>
<!-- Progress bar -->
<div lx-progress="75"></div>
navX — Navigation
Prefix: nx-*
Client-side routing and navigation enhancement.
<!-- SPA-style navigation -->
<a href="/about" nx-link>About Us</a>
<!-- Active state on current page -->
<nav>
<a href="/" nx-link nx-active-class="current">Home</a>
<a href="/products" nx-link nx-active-class="current">Products</a>
</nav>
<!-- Page content container -->
<main nx-outlet></main>
dragX — Drag & Drop
Prefix: dx-*
Make elements draggable with drop zone support.
<!-- Draggable item -->
<div dx-draggable="card">Drag me</div>
<!-- Drop zone -->
<div dx-drop-zone="cards">Drop cards here</div>
<!-- Sortable list -->
<ul dx-sortable>
<li dx-draggable>Item 1</li>
<li dx-draggable>Item 2</li>
<li dx-draggable>Item 3</li>
</ul>
bindX — Data Binding
Prefix: bx-*
Reactive data binding for dynamic content.
<!-- Two-way binding -->
<input type="text" bx-model="name">
<p>Hello, <span bx-text="name"></span>!</p>
<!-- Conditional display -->
<div bx-show="isLoggedIn">Welcome back!</div>
<!-- List rendering -->
<ul bx-for="item in items">
<li bx-text="item.name"></li>
</ul>
<!-- Event handling -->
<button bx-on:click="handleClick">Click me</button>
tableX — Tables
Prefix: tx-*
Enhanced tables with sorting, filtering, and pagination.
<table tx-sortable>
<thead>
<tr>
<th tx-sort="name">Name</th>
<th tx-sort="date" tx-sort-type="date">Date</th>
<th tx-sort="price" tx-sort-type="number">Price</th>
</tr>
</thead>
<tbody>
<tr>
<td>Widget</td>
<td>2024-03-15</td>
<td>29.99</td>
</tr>
<!-- More rows -->
</tbody>
</table>
<!-- With pagination -->
<table tx-sortable tx-paginate="10">
<!-- ... -->
</table>
smartX — Auto-Format
Prefix: sx-*
Automatically detect and format content based on patterns.
<!-- Auto-detect formatting -->
<span sx-auto>$1,234.56</span>
<span sx-auto>(555) 123-4567</span>
<span sx-auto>2024-03-15</span>
<span sx-auto>[email protected]</span>
<!-- Smart links -->
<span sx-linkify>Visit https://example.com</span>
uiX — UI Components
Prefix: ux-*
A complete UI component library with declarative attributes. Most components are pure CSS/HTML. Interactive components use declarative HTML triggers — no custom JavaScript required.
Button
<!-- Basic variants -->
<button ux-enhance="button" ux-variant="primary">Primary</button>
<button ux-enhance="button" ux-variant="secondary">Secondary</button>
<button ux-enhance="button" ux-variant="danger">Danger</button>
<!-- Sizes -->
<button ux-enhance="button" ux-variant="primary" ux-size="sm">Small</button>
<button ux-enhance="button" ux-variant="primary" ux-size="lg">Large</button>
<!-- Custom colors -->
<button ux-enhance="button" ux-bg="pink" ux-hover-bg="hotpink">Pink</button>
Badge & Avatar
<!-- Badge -->
<span ux-enhance="badge" ux-variant="success">Active</span>
<span ux-enhance="badge" ux-bg="purple" ux-color="white">Custom</span>
<!-- Avatar with initials -->
<div ux-enhance="avatar" ux-size="lg" ux-bg="teal">JD</div>
<!-- Avatar with image -->
<div ux-enhance="avatar" ux-size="xl">
<img src="profile.jpg" alt="Jane Doe">
</div>
Card
<!-- Basic card with auto-generated header -->
<div ux-enhance="card" ux-title="My Card">
Card content goes here.
</div>
<!-- Styled card -->
<div ux-enhance="card" ux-title="Styled" ux-header-bg="primary" ux-header-color="white" ux-elevated>
Content with elevated shadow.
</div>
Modal
<!-- Declarative HTML triggers - no custom JavaScript required -->
<button ux-opens="#my-modal">Open Modal</button>
<div ux-enhance="modal" ux-title="Confirm Action" id="my-modal">
<p>Are you sure you want to continue?</p>
<button ux-closes>Cancel</button>
<button ux-closes>Confirm</button>
</div>
ux-opens="#id" opens a modal/drawer. ux-closes closes the nearest parent (or specify ux-closes="#id").
Tabs
<!-- Simple tabs - auto-generates tab buttons -->
<div ux-enhance="tabs" ux-tabs="Home, Profile, Settings" id="my-tabs">
<div>Home content</div>
<div>Profile content</div>
<div>Settings content</div>
</div>
<!-- External tab selection (declarative) -->
<button ux-selects="#my-tabs" ux-tab="Settings">Go to Settings</button>
<!-- Custom colors -->
<div ux-enhance="tabs" ux-tabs="Tab 1, Tab 2" ux-active-bg="primary" ux-active-color="white">
<div>Content 1</div>
<div>Content 2</div>
</div>
Use ux-selects="#id" ux-tab="name" to switch tabs from anywhere. Or use ux-index="0" for index-based selection.
Accordion
<div ux-enhance="accordion" id="my-accordion">
<div class="ux-accordion__item">
<button class="ux-accordion__header">Section 1</button>
<div class="ux-accordion__content">Content 1</div>
</div>
<div class="ux-accordion__item">
<button class="ux-accordion__header">Section 2</button>
<div class="ux-accordion__content">Content 2</div>
</div>
</div>
<!-- External toggle (declarative) -->
<button ux-toggles="#my-accordion" ux-index="0">Toggle Section 1</button>
Use ux-toggles="#id" ux-index="n" to toggle accordion items from anywhere.
Dropdown
<div ux-enhance="dropdown" id="my-dropdown">
<button class="ux-dropdown__trigger">Options</button>
<div class="ux-dropdown__menu">
<a href="#" class="ux-dropdown__item">Edit</a>
<a href="#" class="ux-dropdown__item">Delete</a>
</div>
</div>
<!-- External toggle (declarative) -->
<button ux-toggles="#my-dropdown">Toggle Dropdown</button>
Form Inputs
<!-- Enhanced input -->
<input ux-enhance="input" ux-size="lg" placeholder="Large input">
<!-- Input with error state (red border) -->
<input ux-enhance="input" ux-error="true" placeholder="Invalid input">
<!-- Input with success state (green border) -->
<input ux-enhance="input" ux-success="true" placeholder="Valid input">
<!-- Textarea -->
<textarea ux-enhance="textarea" ux-focus-border="primary"></textarea>
<!-- Textarea with error/success states -->
<textarea ux-enhance="textarea" ux-error="true"></textarea>
<textarea ux-enhance="textarea" ux-success="true"></textarea>
<!-- Select -->
<select ux-enhance="select">
<option>Option 1</option>
<option>Option 2</option>
</select>
<!-- Select with error/success states -->
<select ux-enhance="select" ux-error="true">...</select>
<select ux-enhance="select" ux-success="true">...</select>
<!-- Checkbox with label -->
<input type="checkbox" ux-enhance="checkbox" ux-label="Accept terms">
<!-- Switch toggle -->
<input type="checkbox" ux-enhance="switch" ux-label="Dark mode" ux-on-bg="success">
Navigation
<!-- Nav component -->
<nav ux-enhance="nav" ux-active-bg="primary" ux-active-color="white">
<a href="/" class="ux-nav__item is-active">Home</a>
<a href="/about" class="ux-nav__item">About</a>
<a href="/contact" class="ux-nav__item">Contact</a>
</nav>
<!-- Breadcrumb -->
<nav ux-enhance="breadcrumb">
<a href="/" class="ux-breadcrumb__item">Home</a>
<span class="ux-breadcrumb__separator">/</span>
<a href="/products" class="ux-breadcrumb__item">Products</a>
<span class="ux-breadcrumb__separator">/</span>
<span class="ux-breadcrumb__item">Shoes</span>
</nav>
Tooltip & Spinner
<!-- Tooltip -->
<span ux-enhance="tooltip" ux-content="Helpful tip!" ux-bg="dark">Hover me</span>
<span ux-enhance="tooltip" ux-content="Large tip" ux-size="lg">Hover</span>
<!-- Spinner -->
<div ux-enhance="spinner"></div>
<div ux-enhance="spinner" ux-size="lg" ux-color="primary"></div>
Color Customization
All uiX components support color customization via attributes:
<!-- Use named colors -->
<button ux-enhance="button" ux-bg="tomato">Tomato</button>
<!-- Use hex colors -->
<span ux-enhance="badge" ux-bg="#6366f1" ux-color="white">Indigo</span>
<!-- Use variant names (maps to design tokens) -->
<button ux-enhance="button" ux-bg="primary">Primary</button>
<button ux-enhance="button" ux-bg="success">Success</button>
<button ux-enhance="button" ux-bg="danger">Danger</button>
<!-- Auto-contrast: text color auto-calculated from background -->
<span ux-enhance="badge" ux-bg="yellow">Auto dark text</span>
<span ux-enhance="badge" ux-bg="navy">Auto light text</span>
Variant names: primary, secondary, success, danger, warning, info, neutral
Declarative HTML Triggers
Control interactive components with declarative HTML attributes - no custom JavaScript required:
| Attribute | Action | Example |
|---|---|---|
ux-opens="#id" |
Opens modal/drawer | <button ux-opens="#my-modal"> |
ux-closes |
Closes nearest modal/drawer | <button ux-closes>Cancel</button> |
ux-toggles="#id" |
Toggles dropdown/accordion | <button ux-toggles="#menu"> |
ux-selects="#id" ux-tab="name" |
Selects tab by name | <button ux-selects="#tabs" ux-tab="Settings"> |
CSS-Driven Components
These components are primarily CSS-driven with minimal JavaScript enhancement:
- Visual: badge, avatar, spinner, skeleton, progress, divider, tag, chip
- Typography: alert, card, tooltip, breadcrumb
- Form styling: input, textarea, select, checkbox, radio, switch
HTMX Integration
uiX pairs perfectly with HTMX for server-driven interactions:
<!-- Load modal content from server -->
<button ux-opens="#user-modal" hx-get="/api/user/123" hx-target="#user-modal .ux-modal__body">
View User
</button>
<!-- Lazy-load tab content -->
<div ux-enhance="tabs" ux-tabs="Overview, Details" hx-trigger="ux:change" hx-get="/api/tab">
<div>Overview content</div>
<div>Loading...</div>
</div>
<!-- Infinite scroll with skeleton -->
<div hx-get="/api/items?page=2" hx-trigger="revealed" hx-swap="beforeend">
<div ux-enhance="skeleton" ux-shape="rect"></div>
</div>
Available Components
uiX includes these components:
- Atoms: button, badge, avatar, spinner, input, textarea, select, checkbox, radio, switch, tag, chip, divider, icon
- Molecules: card, alert, modal, accordion, tabs, dropdown, tooltip, popover, menu, breadcrumb, pagination, progress, skeleton
- Organisms: nav, sidebar, table, drawer, toast, stepper
Framework Compatibility
genX works with any framework because it operates on the DOM after rendering. Use it alongside your existing stack.
React
function ProductCard({ price }) {
return (
<div className="product">
<span fx-format="currency">{price}</span>
</div>
);
}
Vue
<template>
<div class="product">
<span fx-format="currency">{{ price }}</span>
</div>
</template>
htmx
genX and htmx complement each other perfectly:
<!-- htmx loads content, genX formats it -->
<div hx-get="/api/products" hx-trigger="load">
<!-- Server returns: <span fx-format="currency">29.99</span> -->
<!-- genX automatically formats to: $29.99 -->
</div>
Server-Side (Django, Rails, Laravel, PHP)
genX is ideal for server-rendered HTML. Your backend outputs raw values, genX formats them:
<!-- Django -->
<span fx-format="currency">{{ product.price }}</span>
<!-- Rails -->
<span fx-format="currency"><%= product.price %></span>
<!-- Laravel -->
<span fx-format="currency">{{ $product->price }}</span>
<!-- PHP -->
<span fx-format="currency"><?= $product['price'] ?></span>
Troubleshooting
Elements Not Formatting
Check:
- Script is loading (check browser console for errors)
- Script has
deferattribute - Attribute names are correct (
fx-format, notfx_formatordata-fx-format) - Values are valid (numbers for currency, ISO dates for dates)
Dynamic Content Not Processing
Elements added via JavaScript should process automatically. If not:
- Verify elements are added to the DOM, not just created
- Check for JavaScript errors blocking execution
- Ensure MutationObserver is supported (all modern browsers)
Table Sorting Not Working
Check:
tx-sortableclass is on<th>elements- Table has proper
<thead>and<tbody>structure - No conflicting JavaScript handling click events
Common Console Errors
| Error | Fix |
|---|---|
genX is not defined |
Check script URL and network tab |
Invalid date |
Use ISO format: 2024-03-15 |
NaN |
Ensure numeric values are clean |
Browser Support
genX supports all modern browsers:
- Chrome 90+
- Firefox 88+
- Safari 14+
- Edge 90+
Requirements: ES6+, Proxy, MutationObserver, async/await
Performance
genX is designed for speed:
- Bootloader: <5ms to scan 1000 elements
- Parsing: <100ms for 1000 elements
- Operations: <16ms (60 FPS target)
- Module init: <105ms total bootstrap
The bootloader uses MutationObserver to watch for dynamic content, so elements added after page load are automatically processed.