RAVN Logo RAVN

From blank HTML to SaaS Dashboard in 5 minutes.

No Tailwind config. No build step. No setup. Just paste the CDN link and ship high-density, production-ready interfaces instantly. ~25KB total. 13 premium themes.

$ Copy CDN Link

Installation

Integrate RAVN UI into your project in seconds. No build tools required for CDN usage.

CDN
Package Manager
Starter HTML
Copy
<!-- Core Styles --> <link rel="stylesheet" href="https://unpkg.com/@ravn-ui/core/dist/ui.css"> <link rel="stylesheet" href="https://unpkg.com/@ravn-ui/core/dist/themes.css"> <!-- Core Logic --> <script src="https://unpkg.com/@ravn-ui/core/dist/ui.js"></script>
# Using Bun (Recommended) bun add @ravn-ui/core # Using NPM npm install @ravn-ui/core
<!DOCTYPE html> <html lang="en" data-theme="light"> <head> <link rel="stylesheet" href="https://unpkg.com/@ravn-ui/core/dist/ui.css"> <link rel="stylesheet" href="https://unpkg.com/@ravn-ui/core/dist/themes.css"> </head> <body> <button class="btn btn-primary">Hello RAVN</button> <script src="https://unpkg.com/@ravn-ui/core/dist/ui.js"></script> </body> </html>

Building with an AI Agent? Use our machine-readable llms.txt for instant context.

Theming

RAVN UI is built on a robust token system. Apply themes globally via the data-theme attribute.

HTML
JavaScript
Copy
<!-- Apply midnight theme globally --> <html data-theme="midnight"> ... </html>
// Switch themes dynamically with persistence RAVN.setTheme('supabase'); // Available themes: // light, dark, claude, midnight, supabase, linear, // zinc, forest, indigo, retro, pixel-craft, rose-pine, nord

Buttons

High-precision action triggers with consistent internal padding and clear focus states.

Preview
Source
Copy
<button class="btn btn-primary">Primary</button>
<button class="btn btn-outline">Secondary</button>
<button class="btn btn-ghost">Ghost</button>
<button class="btn btn-primary btn-sm">Small</button>

Inputs

Refined data entry fields with consistent focus rings and utility states.

Preview
Source
Copy
Unique name for your workspace.
Please enter a valid email address.
Username is available!
API key is disabled for this project.
<div class="form-group">
  <label class="label">Project Name</label>
  <input type="text" class="input" placeholder="e.g. Apollo Dashboard">
  <span class="helper-text">Unique name for your workspace.</span>
</div>

<!-- Error State -->
<div class="form-group">
  <label class="label">Email Address</label>
  <input type="email" class="input input-error" value="invalid-email">
  <span class="helper-text" style="color: var(--error);">Please enter a valid email address.</span>
</div>

<!-- Success State -->
<div class="form-group">
  <label class="label">Username</label>
  <input type="text" class="input input-success" value="ravn_developer">
  <span class="helper-text" style="color: var(--success);">Username is available!</span>
</div>

<!-- Disabled State -->
<div class="form-group">
  <label class="label">API Key</label>
  <input type="password" class="input" disabled value="••••••••••••••••">
  <span class="helper-text">API key is disabled for this project.</span>
</div>

Cards

Modular containers designed for data density and hierarchical clarity.

Preview
Source
Copy

Revenue Stream

Monthly recurring revenue analysis.
$14,290.00
↑ 12.5% from last month

Quick Actions

Common operations for this project.
<!-- Metric Card -->
<div class="card">
  <div class="card-header">
    <h3>Revenue Stream</h3>
    <small>Monthly recurring revenue analysis.</small>
  </div>
  <div class="card-content">
    <div style="font-size: 1.5rem; font-weight: 700;">$14,290.00</div>
    <div class="trend trend-up">↑ 12.5% from last month</div>
  </div>
  <div class="card-footer">
    <button class="btn btn-outline btn-sm w-full">View Full Report</button>
  </div>
</div>

<!-- Actions Card -->
<div class="card">
  <div class="card-header">
    <h3>Quick Actions</h3>
  </div>
  <div class="card-content flex gap-2">
    <button class="btn btn-primary btn-sm">Primary</button>
    <button class="btn btn-secondary btn-sm">Invite</button>
  </div>
</div>

Tables

High-density data grids with refined hover states and header alignment.

Preview
Source
Copy
Customer Status Amount
Alex Rivera Paid $240.00
Sarah Chen Pending $1,200.00
<div class="table-container">
  <table class="table">
    <thead>
      <tr>
        <th>Customer</th>
        <th>Status</th>
        <th>Amount</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <td>Alex Rivera</td>
        <td><span class="badge">Paid</span></td>
        <td>$240.00</td>
      </tr>
      <tr>
        <td>Sarah Chen</td>
        <td><span class="badge badge-secondary">Pending</span></td>
        <td>$1,200.00</td>
      </tr>
    </tbody>
  </table>
</div>

Avatars

High-fidelity profile representation.

Preview
Source
Copy
JD
RV
User
<!-- Simple Text -->
<div class="avatar">JD</div>

<!-- Primary Variant -->
<div class="avatar" style="background: var(--primary); color: var(--primary-foreground);">RV</div>

<!-- Image variant -->
<div class="avatar">
  <img src="user.jpg" alt="Avatar">
</div>

Toggles & Status

High-fidelity binary controls and real-time state indicators.

Preview
Source
Copy
Push Notifications
System Live
<div class="flex items-center gap-8">
  <div class="flex items-center gap-3">
    <input type="checkbox" class="switch" checked>
    <span class="text-sm">Push Notifications</span>
  </div>
  <div class="status">
    <div class="status-dot status-online"></div>
    System Live
  </div>
</div>

Accordions

Expandable containers for hierarchical information or FAQs. Optimized for accessibility with Space/Enter trigger support.

Preview
Source
Copy
How do I install RAVN UI?
You can install RAVN UI via Bun, NPM, or simply by including the CDN links in your HTML head.
Is it compatible with Tailwind?
Yes, RAVN UI uses standard CSS variables and classes that can coexist perfectly with Tailwind or any other CSS framework.
<div class="accordion">
  <div class="accordion-item">
    <div class="accordion-trigger">How do I install RAVN UI?</div>
    <div class="accordion-content">
      You can install RAVN UI via Bun, NPM, or simply by including the CDN links in your HTML head.
    </div>
  </div>
  <div class="accordion-item">
    <div class="accordion-trigger">Is it compatible with Tailwind?</div>
    <div class="accordion-content">
      Yes, RAVN UI uses standard CSS variables and classes that can coexist perfectly with Tailwind.
    </div>
  </div>
</div>

Skeletons

Progressive loading states with smooth pulse animations.

Preview
Source
Copy
<div class="flex items-center gap-4">
  <div class="avatar skeleton"></div>
  <div class="flex flex-col gap-1">
    <div class="skeleton" style="width: 120px; height: 16px;"></div>
    <div class="skeleton" style="width: 80px; height: 12px;"></div>
  </div>
</div>

Forms

High-density form layouts for enterprise configuration.

Preview
Source
Copy

Project Settings

Manage your workspace configuration.
This will be visible on your invoices.
Make profile public
<div class="card">
  <div class="card-header">
    <h3>Project Settings</h3>
    <small>Manage your workspace configuration.</small>
  </div>
  <div class="card-content">
    <div class="form-group">
      <label class="label">Organization Name</label>
      <input type="text" class="input" placeholder="e.g. Acme Corp">
      <span class="helper-text">This will be visible on your invoices.</span>
    </div>
    <div class="form-group">
      <label class="label">Visibility</label>
      <div class="flex items-center gap-3">
        <input type="checkbox" class="switch">
        <span class="text-sm">Make profile public</span>
      </div>
    </div>
  </div>
  <div class="card-footer">
    <button class="btn btn-primary w-full">Save Changes</button>
  </div>
</div>

Alerts

Contextual feedback messages for user actions and system states.

Preview
Source
Copy
Terminal access has been granted to this session.
Payment processed successfully. Transaction ID: #8291.
Failed to sync with the database. Please check your connection.
<!-- Default -->
<div class="alert">
  <span>Terminal access has been granted to this session.</span>
</div>

<!-- Success -->
<div class="alert alert-success">
  <span>Payment processed successfully. Transaction ID: #8291.</span>
</div>

<!-- Error -->
<div class="alert alert-error">
  <span>Failed to sync with the database. Please check your connection.</span>
</div>

Modals

High-fidelity dialogs for critical actions and focused tasks.

Preview
Source
Copy

Progress

Visual indicators for task completion and capacity.

Preview
Source
Copy
Storage Limit 75%
System Uptime 99.9%
<div class="progress">
  <div class="progress-bar" style="width: 75%;"></div>
</div>

<!-- Colored variant -->
<div class="progress">
  <div class="progress-bar" style="width: 99%; background: var(--success);"></div>
</div>

Tooltips

Zero-JS contextual information on hover.

Preview
Source
Copy
Hover me
<!-- Basic Text -->
<span data-tooltip="This is a top tooltip">Hover me</span>

<!-- On a button -->
<button class="btn btn-primary" data-tooltip="Saves your changes">Save Changes</button>

Dashboard Patterns

High-density SaaS layout patterns for complex data interfaces.

Preview
Source
Copy
Total Revenue
$45,231.89
↑ 20.1%
Subscriptions
+2,350
↑ 180.1%
Active Now
+573
↓ 12

Recent Transactions

CustomerStatusAmount
Alex RiveraPaid$240.00
Sarah ChenPending$1,200.00
📊

Analytics Dashboard

Real-time data stream visualization would go here.

<!-- Dashboard Shell -->
<div style="display: flex; height: 500px; border: 1px solid var(--border);">
  <!-- Sidebar -->
  <aside class="sidebar" style="width: 200px; border-right: 1px solid var(--border);">
    <nav class="sidebar-nav">
      <a href="#" class="sidebar-item active">Overview</a>
      <a href="#" class="sidebar-item">Analytics</a>
    </nav>
  </aside>

  <!-- Main Content -->
  <main style="flex: 1; display: flex; flex-direction: column;">
    <header style="height: 56px; border-bottom: 1px solid var(--border); display: flex; align-items: center; padding: 0 var(--space-6);">
      <div class="breadcrumbs">
        <a href="#" class="breadcrumb-item">Project</a>
        <span class="breadcrumb-item active">Overview</span>
      </div>
    </header>

    <div style="padding: var(--space-6);">
      <!-- Metrics Grid -->
      <div style="display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--space-4);">
        <div class="card" style="padding: var(--space-4);">
          <div style="font-size: 0.7rem; color: var(--muted-foreground);">Total Revenue</div>
          <div style="font-size: 1.5rem; font-weight: 700;">$45,231.89</div>
          <div class="trend trend-up">↑ 20.1%</div>
        </div>
        <!-- Add more cards... -->
      </div>
    </div>
  </main>
</div>

Core API Reference

RAVN UI ships with a lightweight, framework-agnostic runtime exposed globally under window.RAVN.

RAVN.store

A simple global state management system. No Redux, no context API.

// Set state
RAVN.store.set('todos', [{ id: 1, text: 'Ship faster' }]);

// Get state
const todos = RAVN.store.get('todos');

// Subscribe to changes
const unsubscribe = RAVN.store.subscribe((key, val, state) => {
    if (key === 'todos') console.log('Todos updated!', val);
});

RAVN.route(path)

Built-in router for SPA applications. Automatically toggles data-route blocks and pushes history state.

// Navigate to a view
RAVN.route('dashboard');

// Run a hook when a view loads
RAVN.onViewEnter('dashboard', () => {
    fetchAnalytics();
});

RAVN.on(event, selector, handler)

High-performance event delegation. Stop writing inline onclick attributes.

RAVN.on('click', '[data-action="delete"]', (event, target) => {
    const id = target.getAttribute('data-id');
    deleteItem(id);
});

RAVN.fetch(url, options)

Minimal wrapper over the native fetch API that assumes JSON payloads.

const user = await RAVN.fetch('/api/user', {
    method: 'POST',
    body: JSON.stringify({ name: 'John' })
});

Golden Patterns

Adhere to these rules to maintain an elite, fast, and scalable codebase without relying on a VDOM framework.

✅ DO: Micro Components

Write pure functions that take data and return HTML strings. Compose them like React.

function Card(title, content) {
    return `
        <div class="card p-4">
            <h3>${title}</h3>
            <div>${content}</div>
        </div>
    `;
}

❌ DON'T: Inline Handlers

Never use onclick="..." in your HTML string components. It breaks CSP and makes code hard to test.

// BAD
return `<button onclick="save()">Save</button>`;

// GOOD
return `<button data-action="save">Save</button>`;
// Handled by RAVN.on('click', '[data-action="save"]', ...)

The Standard Render Cycle

Use a single entry point for rendering your views to keep state predictable.

function renderTodos() {
    const list = document.getElementById('todo-list');
    if (!list) return;
    
    const todos = RAVN.store.get('todos') || [];
    list.innerHTML = todos.map(t => TodoItem(t)).join('');
}

// Re-render when state changes
RAVN.store.subscribe((key) => {
    if (key === 'todos') renderTodos();
});

Examples

Drop these copy-paste snippets into your app to build complex layouts in minutes.

Vanilla Todo App

// Component
function TodoItem(item) {
    return `
    <div class="flex items-center justify-between p-3 border-b">
        <span class="${item.done ? 'text-muted-foreground line-through' : ''}">${item.text}</span>
        <button class="btn btn-ghost btn-sm text-error" data-action="delete-todo" data-id="${item.id}">×</button>
    </div>`;
}

// Logic
document.addEventListener('DOMContentLoaded', () => {
    RAVN.store.set('todos', [{ id: 1, text: 'Learn RAVN', done: false }]);

    RAVN.on('click', '[data-action="add-todo"]', () => {
        const input = document.getElementById('new-todo');
        const todos = RAVN.store.get('todos');
        RAVN.store.set('todos', [...todos, { id: Date.now(), text: input.value, done: false }]);
        input.value = '';
    });

    RAVN.on('click', '[data-action="delete-todo"]', (e, el) => {
        const id = parseInt(el.getAttribute('data-id'));
        const todos = RAVN.store.get('todos');
        RAVN.store.set('todos', todos.filter(t => t.id !== id));
    });

    RAVN.store.subscribe((key) => {
        if (key === 'todos') {
            document.getElementById('todo-list').innerHTML = 
                RAVN.store.get('todos').map(TodoItem).join('');
        }
    });
});