A native UI system for the Altair framework
Built on Crystal · ECR · Tailwind CSS
Components & Contracts — not scattered HTML, CSS, and JavaScript.
Altair UI is not just a component library built on top of Tailwind.
It is a native UI layer inside the Altair framework, connecting:
- Crystal — real, type-safe APIs (not HTML snippets)
- ECR — natural composition inside templates
- Semantic HTML — semantic-first markup
- Tailwind CSS — a design engine, not the component interface
- Server & browser behavior — unified under a single contract
The core idea: developers work with Components and Contracts, instead of manually wiring HTML, CSS, JavaScript, forms, validation, and server actions separately.
flowchart TD
A["Altair UI"] --> B["Component API"]
A --> C["Server Behavior"]
A --> D["Browser Behavior"]
B --> E["Tailwind CSS"]
C --> E
D --> E
E --> F["Altair / External JS"]
F --> G["Browser"]
classDef ui fill:#4b5563,stroke:#374151,color:#ffffff;
class A,B,C,D,E,F,G ui
Instead of hand-writing this:
HTML + CSS + JavaScript + validation + CSRF + routes + API requests + error rendering
You write this:
<%= ui.form @product do |form| %>
<%= form.input :name %>
<%= form.input :price %>
<%= form.select :category_id, categories %>
<%= form.submit "Create Product" %>
<% end %>Everything else — binding, styling, security — is the system's responsibility.
| # | Principle |
|---|---|
| 1 | Crystal-native first — components are real Crystal APIs with type safety, variants, and composition |
| 2 | A component is not just HTML — presentation + browser behavior + server behavior |
| 3 | JavaScript is opt-in, not mandatory — progressive enhancement over requirement |
| 4 | Tailwind powers the design; it does not define the API — Altair UI ≠ Tailwind wrapper |
| 5 | Adapters, not dependencies — HTMX, Alpine.js, and Preact are optional integrations |
HTML-first · CSS-first · Server-first · JavaScript-last
An official architectural rule: every component declares its JavaScript dependency.
| Class | Description | Runtime | Examples |
|---|---|---|---|
| Zero-JS | Works entirely without JavaScript | none |
Button · Card · Input · Form · Badge · Alert · Pagination |
| Progressive-JS | HTML first, optional enhancement | optional |
Modal · Dropdown · Tabs · Toast · Combobox |
| Rich-JS | Requires client-side interactivity by nature | required |
DataGrid · Rich Text Editor · Charts · Drag & Drop |
The golden rule: JS enhancement — not JS requirement.
Altair UI is not bound to a single JavaScript framework. The Component Contract stays neutral:
flowchart TD
CC["Component Contract"] --> N["Native"]
CC --> AR["Altair Runtime"]
CC --> AD["Adapters"]
AD --> H["HTMX<br/><i>hx-*</i>"]
AD --> AL["Alpine.js<br/><i>x-data</i>"]
AD --> P["Preact<br/><i>Islands</i>"]
classDef ui fill:#4b5563,stroke:#374151,color:#ffffff;
class CC,N,AR,AD,H,AL,P ui
Altair UI owns the component contract; external JavaScript libraries own specialized client behavior.
<%= ui.button(
"Delete",
variant: :danger,
hx: {
delete: "/products/42",
target: "#product-42",
swap: "outerHTML"
}
) %>Remove HTMX? The component API remains fully valid.
<%= ui.island "#product-editor", framework: :preact %>Server-render the application; hydrate only the parts that need it.
Altair UI's key differentiator: components understand your server-side model.
flowchart LR
M["Model"] --> F["Fields"] --> T["Types"] --> V["Validation"] --> E["Errors"] --> C["CSRF"] --> R["Route"] --> S["Response"]
Once primitives stabilize, this unlocks higher-level APIs:
<%= ui.auto_form @product %> <%# Fully generated form %>
<%= ui.table Product.all %> <%# Fully generated table %>With full override support when you need control:
<%= ui.auto_form @product do |form| %>
<%= form.field :name %>
<%= form.field :price, prefix: "$" %>
<%= form.submit "Create" %>
<% end %>flowchart TB
F["Foundation<br/><i>Colors · Typography · Spacing · Icons · Focus States</i>"] --> P["Primitives<br/><i>Button · Input · Label · Badge · Avatar</i>"]
P --> C["Composite<br/><i>Form · Card · Dialog · Dropdown · Tabs · Toast</i>"]
C --> A["Application<br/><i>Data Table · Data Grid · Pagination · Command Interface</i>"]
classDef ui fill:#4b5563,stroke:#374151,color:#ffffff;
class F,P,C,A ui
Every component ships with discoverable metadata so developers know its cost before using it:
| Modal | |
|---|---|
| JavaScript | Progressive-JS |
| Runtime | optional |
| Bundle | small |
| Tailwind | yes |
| Server-aware | no |
| Adapters | HTMX, Alpine |
The CLI is part of the product:
altair ui add button # Add a component
altair ui add modal --engine alpine # Add one with an adapter
altair ui info modal # Inspect capabilities & metadata
altair ui adapters list # List available adapters
altair ui doctor # Validate project healthThe CLI generates source into your project — you own the code:
lib/
└── altair_ui/
├── components/
├── themes/
└── adapters/
Governing rule: no external integration ships before the core contract is proven.
| Phase | Scope |
|---|---|
| 0 | Foundation & Rules — vision · contracts · taxonomy · JS charter |
| 1 | Design Foundation — tokens · Tailwind · accessibility |
| 2 | Crystal-native Core — base API · rendering · first components |
| 3 | Server-aware UI — form engine · actions · auto UI |
| 4 | Native Browser Runtime — progressive components · lifecycle |
| 5 | CLI & Registry — add/info/doctor · source ownership |
| 6 | Integrations — HTMX · Alpine · Preact islands · public adapter API |
| 7 | Advanced Components — data grid · command menu · charts |
| 8 | DX & Maturity — docs · explorer · testing · performance |
- ❌ A Tailwind wrapper — static class strings are not the value proposition
- ❌ A new JavaScript framework — no heavyweight runtime, no reinvented state management
- ❌ Bound to HTMX, Alpine, or Preact — all are optional adapters
- ❌ An SPA framework — Altair is server-rendered first
Altair UI doesn't answer "which JavaScript framework should I use?"
It answers:
What should the developer's UI contract be — and how can it be delivered at the lowest possible cost?
Crystal-native + HTML-first + Tailwind-powered +
Server-aware + JavaScript-optional + Adapter-friendly + Islands-capable
Altair UI — a native part of the Altair experience, not just another design library.