dolphin-client
v1.1.7
Published
HTML is back! Hookless, framework-agnostic real-time reactive DOM-binding client for Dolphin Server with WebSockets, WebRTC signaling, and offline REST API fallbacks.
Downloads
875
Maintainers
Readme
dolphin-client 🐬 — HTML is back!
Hookless, framework-agnostic, zero-dependency real-time reactive DOM-binding engine.
Unleash the full power of modern native browser APIs and DolphinCSS without the heavy framework tax of React or Vue!
💌 Returning Home: A Love Letter to HTML
Remember the early days of your coding journey? Writing a simple index.html in a plain text editor, double-clicking it, and watching it open instantly in the browser. No complex build pipelines, no node_modules weighing hundreds of megabytes, no state hooks, and no framework fatigue. Just a direct, pure, and magical relationship between your markup and the browser.
Over the last decade, we treated HTML as a dead, passive mounting point (<div id="root"></div>) while building virtual universes in JavaScript. We spent 80% of our time debugging configurations and boilerplate, and only 20% building beautiful user experiences.
Dolphin Client is our way of coming home.
By breathing life back into standard HTML, we have resurrected the simplicity of standard markup and empowered it with the modern superpowers of WebSockets, IndexedDB, WebRTC, and hardware-accelerated CSS variables. It is the renaissance of the native web standards we all fell in love with.
Because the best JavaScript is actually the code you never had to write.
Documentation
[!TIP] 📖 Read our comprehensive Full Developer Tutorial & Integration Guide for detailed guides, Next.js setups, WebRTC intercoms, global stores, drag-and-drop sortable lists, and real-world examples!
Features
- Universal Backend Compatibility: Native out-of-the-box support for PHP (Laravel, CakePHP, WordPress) and Node.js (Express, NestJS, Fastify). Auto-extracts/injects CSRF tokens and nonces, normalizes multi-format validation error payloads directly into reactive forms, and supports HTTP method spoofing (
_method) and subfolder base URLs automatically. - HTML Component Imports (
data-import): Declaratively import reusable layouts (e.g.header.html,footer.html) dynamically in pure HTML with robust concurrent promise caching, nested rendering, and circular dependency checks. - React-Style Reusable Components (
<dolphin-component>): Load external HTML templates viasrc, pass props as attributes, inject default and named slots (slot="actions"), and get per-instance isolated reactive stores—just like React components, with zero build step. - Instant SPA Viewport Router (
data-spa): Converts static pages into highly responsive Single Page Applications (SPAs) with zero manual JS. High-jacks links, swaps viewports dynamically with smooth fading transitions, and updates page titles and history navigation (popstate). - Hookless Reactivity: Bind topics to DOM elements via HTML data attributes—no React, Vue, or Angular state management required.
- Svelte-Style Templates Compiler: Native browser compiler supporting Svelte-style loop blocks (
{#each ... as ...}), keyed lists ({#each items as item (item.id)}), multi-level nested conditionals ({#if} / {:else if} / {:else}), loop indices (index), optional chaining, and dynamic attribute interpolation. - Keyed Virtual DOM Reconciliation: Large lists use
data-dolphin-keyfor React-style stable DOM updates—preserving input focus, scroll position, and node identity on reorder, insert, and delete. - Unified Event Binding: Loop-based browser event handling for values (
data-rt-push) and actions (data-rt-[event]/data-api-[event]). - Context API/Prop drilling in Pure DOM: Crawls up the DOM tree (
getClosestContext) to fetch parent contexts and inject parameters. - REST API + Realtime Hybrid Support: Evaluates templates (
data-rt-template) on initial HTTP fetches (data-api-get) and transitions seamlessly to real-time WebSockets on connection. - WebRTC Intercom Signaling: Built-in methods to handle peer connections, track negotiation, ICE candidates, and signaling.
- Hookless React Integration (
dolphin-client/react): Official React adapter —DolphinProvider,useDolphin(),useDolphinStore(). React renders UI; Dolphin handles data, WebSocket sync, API, offline, and mutations. One bridge hook, zerouseEffectchains. - DolphinStore JS API: Programmatic store query, filtering (
where), sorting (orderBy), and live collection syncing with auto-REST/WS fallback. - Ultralight weight: Zero external dependencies, pure browser-native runtime APIs (~47KB compressed bundle!).
Installation & Setup
Method 1: NPM (For Modern Bundlers)
npm install dolphin-clientMethod 2: Direct Local Download (For No-Install / Plain HTML)
Tired of the command line and node_modules clutter? We've got you covered!
[!IMPORTANT] How to Download the JS Files: Clicking the JS download buttons will display the raw JavaScript code in your browser. To download it as a file:
- Right-click on the yellow/blue button and select "Save Link As..." (or "Save Target As...").
- Or, if you clicked it, press
Ctrl + S(orCmd + Son Mac) on the code page to save it.- Alternatively, run these commands in your terminal to download directly:
- Standard (Development):
curl -o dolphin-client.js https://unpkg.com/dolphin-client/dist/dolphin-client.js- Minified (Production):
curl -o dolphin-client.min.js https://unpkg.com/dolphin-client/dist/dolphin-client.min.js
[!TIP] If the ZIP file download is unavailable: You can clone this repository directly or copy the
dist/dolphin-client.js(ordist/dolphin-client.min.js) file from your clone. For the premium styling layer, create adolphin-css.cssfile and add the custom effects (like.fx-glassand.fx-neon) described in the Full Developer Tutorial.
Extract the zip directly inside your project folder to get a clean local directory structure with pre-bundled assets:
my-project/
├── css/
│ └── dolphin-css.css (DolphinCSS Premium Visuals Layer)
├── js/
│ ├── dolphin-client.js (Standard Reactivity Engine)
│ └── dolphin-client.min.js (Minified Production Reactivity Engine)
└── index.html (A ready-to-run skeleton template!)Inside your HTML, simply link them locally:
<link rel="stylesheet" href="css/dolphin-css.css">
<script src="js/dolphin-client.js"></script>🧠 VS Code Autocomplete (IntelliSense)
Get instant HTML attribute suggestions for all Dolphin Client attributes (data-api-get, data-rt-click, data-store-write, <dolphin-component>, etc.) directly inside VS Code!
For NPM Users
Autocomplete is set up automatically when you install:
npm install dolphin-clientThat's it! Reload VS Code window (Ctrl + Shift + P → Developer: Reload Window) and start typing data- to see suggestions.
For CDN / Direct Download Users
Run this one-time command inside your project folder:
npx dolphin-clientThis will automatically generate .vscode/settings.json and .vscode/dolphin-tags.json in your project, enabling full HTML attribute autocomplete in VS Code.
[!TIP] After running the command, reload VS Code (
Ctrl + Shift + P→Developer: Reload Window) to activate autocomplete. You only need to run this once per project!
Interactive Examples Guide
Below are clean, ready-to-use HTML examples for the core features of Dolphin Client. Because Dolphin supports Zero-Configuration Auto-Initialization, these will run instantly!
1. Real-Time (RT) Pub/Sub (Real-time Chat)
Publish inputs on typing, and display incoming messages in real-time under a WebSocket topic:
<!-- Automatically publishes typed values to topic 'chat/messages' -->
<input name="chatMessage" data-rt-push="chat/messages" placeholder="Type a message..." />
<!-- Displays and appends all incoming messages under 'chat/messages' -->
<div data-rt-bind="chat/messages" data-rt-template='
<div class="message-card">
<span class="user-label">@user:</span>
<p>{{chatMessage}}</p>
</div>
'></div>2. REST API Integration (Reactive List Loader)
Fetch data instantly via REST API on page load and compile templates dynamically:
<!-- Fetches from GET /api/devices, compiles items inside #device-card-template -->
<div data-api-get="/api/devices" data-rt-template="#device-card-template">
<!-- Loading spinner placeholder: automatically removed when data arrives! -->
<div class="spinner">Loading devices...</div>
</div>
<!-- Browser-Native Template Tag (No quote-escaping or backticks needed!) -->
<template id="device-card-template">
<div class="device-card">
<h3>{{name}}</h3>
<span class="badge">{{status}}</span>
</div>
</template>3. Declarative Form Validation
Apply strong validation rules to inputs and display errors directly in the UI with absolutely zero JavaScript:
<form id="login-form" data-api-submit="POST /api/login">
<div class="form-group">
<input name="email" data-validate="required,email" placeholder="Your Email" />
<!-- Automatically reads and displays validation error directly in the UI -->
<span class="error-msg" data-rt-bind="errors/email"></span>
</div>
<div class="form-group">
<input name="password" type="password" data-validate="required,min:8" placeholder="Password" />
<span class="error-msg" data-rt-bind="errors/password"></span>
</div>
<button type="submit">Log In</button>
</form>4. Global State & Declarative Store Actions (No-JS Actions!)
Manage local stores, calculate math, toggle boolean logic, and run database collection operations directly in HTML attributes:
UI State Management:
<!-- 1. Auto-sync inputs directly into store key 'app.username' -->
<input data-store-write="app.username" placeholder="Type name..." />
<h3 data-store-read="app.username"></h3>
<!-- 2. Pure HTML Mathematical Counter -->
<div class="counter-box">
<div class="counter-value" data-store-read="app.count">0</div>
<!-- Updates state directly in HTML click. Dolphin updates the UI dynamically! -->
<button data-store-click="app.count = (app.count || 0) + 1">+</button>
<button data-store-click="app.count = (app.count || 0) - 1">-</button>
</div>
<!-- 3. Complex Calculations & Toggles -->
<button data-store-click="app.area = 3.14159 * (app.radius * app.radius)">Calculate Area</button>
<button data-store-click="app.darkMode = !app.darkMode">Toggle Dark Mode</button>Database Store CRUD & Filters (New in v2.0!):
<!-- 1. Initialize or sync the database collection -->
<dolphin-store name="products"></dolphin-store>
<!-- 2. Search and filter the collection directly from HTML inputs -->
<input placeholder="Search products..." data-store-input="products.search(this.value)" />
<select data-store-change="products.filter('category', this.value)">
<option value="">All Categories</option>
<option value="electronics">Electronics</option>
</select>
<!-- 3. Trigger sorting or reset filters -->
<button data-store-click="products.sort('price', false)">Sort by Price Desc</button>
<button data-store-click="products.clearFilters()">Reset</button>
<!-- 4. Execute database mutations (DOM updates automatically!) -->
<div data-rt-bind="store/products" data-rt-template="#product-list"></div>
<template id="product-list">
{#each items as item (item.id)}
<div>
<span>{{item.name}}</span>
<button data-store-click="products.deleteById(item.id)">Delete</button>
</div>
{/each}
</template>5. React-Style Reusable Components (<dolphin-component>)
Define a component once in an external HTML file, then reuse it with different props and slots—no bundler required:
<!-- components/counter.html — component definition -->
<template id="counter">
<div class="card">
<h3>{{label}}</h3>
<p class="count">{{count}}</p>
<footer>{{slot}}</footer>
<div>{{slot:actions}}</div>
<button data-store-click="count = count + 1">+1</button>
</div>
</template><!-- page.html — multiple independent instances -->
<dolphin-component
src="components/counter.html#counter"
label="Counter A"
count="5">
<span>Default slot content</span>
<button slot="actions">Reset</button>
</dolphin-component>
<dolphin-component
src="components/counter.html#counter"
label="Counter B"
count="100">
<button slot="actions">Export</button>
</dolphin-component>| React | <dolphin-component> |
|-------|----------------------|
| props | HTML attributes (label, count, …) |
| children | default slot → {{slot}} in template |
| named slots | slot="actions" → {{slot:actions}} |
| internal state | isolated per-instance store (store attr or auto _dc_N) |
| useEffect | data-on-mount / data-on-destroy |
6. Hookless React Integration (dolphin-client/react)
React renders. Dolphin thinks. No useState/useEffect for data — one official bridge hook only.
npm install dolphin-client react// app/layout.jsx
import { DolphinProvider } from 'dolphin-client/react';
export default function RootLayout({ children }) {
return (
<DolphinProvider serverUrl="http://localhost:3000" autoConnect>
{children}
</DolphinProvider>
);
}// components/OrdersList.jsx — dumb presentation components
import { useDolphin, useDolphinClient } from 'dolphin-client/react';
function OrderRow({ order, onDelete }) {
return (
<div className="row">
<span>{order.name}</span>
<button onClick={() => onDelete(order.id)}>Delete</button>
</div>
);
}
export function OrdersList() {
const { items, loading, error } = useDolphin('orders');
const dolphin = useDolphinClient();
if (loading) return <p>Loading...</p>;
if (error) return <p>Error: {error}</p>;
return items.map(order => (
<OrderRow
key={order.id}
order={order}
onDelete={(id) => dolphin.store.orders.deleteById(id)}
/>
));
}| Layer | Responsibility |
|-------|----------------|
| React | JSX, layout, design system (MUI, Tailwind, etc.) |
| useDolphin() | Single subscription bridge to DolphinStore |
| Dolphin | Fetch, WebSocket sync, API, offline, mutations |
| Event handlers | Imperative dolphin.store.* calls — no hooks |
Local UI state (tabs, modals, form drafts):
import { useDolphinStore, useDolphinClient } from 'dolphin-client/react';
function ProfileForm() {
const ui = useDolphinStore('app');
const dolphin = useDolphinClient();
return (
<input
value={ui.username || ''}
onChange={(e) => dolphin.setStoreState('app', 'username', e.target.value)}
/>
);
}Next.js: Use Server Components for SEO + initial HTML, wrap client pages in
<DolphinProvider>. See fulltutorial.md — Section 6 & 18.
6.1 Next.js Special: 100% SEO + Zero use client Headaches
Build lightning-fast Next.js apps with 100% SEO and almost no use client directives!
Step 1: Root Layout (Server Component)
// app/layout.tsx
import { DolphinProvider } from 'dolphin-client/react';
import './globals.css';
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="en">
<body>
{/* DolphinProvider initialized with optional serverUrl */}
<DolphinProvider serverUrl="http://localhost:3000" autoConnect>
{children}
</DolphinProvider>
</body>
</html>
);
}Step 2: Page with Server Components + Dolphin (Minimal use client)
// app/products/page.tsx (Mostly Server Components!)
import { getProductsFromDatabase } from '@/lib/db';
import ProductsList from '@/components/ProductsList';
// ⚡ Server Component: No client-side JS needed for initial HTML!
export default async function ProductsPage() {
const initialProducts = await getProductsFromDatabase(); // Server-side DB call
return (
<div className="container mx-auto p-4">
<h1 className="text-3xl font-bold mb-8">Products</h1>
{/* Pass initial server data to the tiny client wrapper */}
<ProductsList initialProducts={initialProducts} />
</div>
);
}// components/ProductsList.tsx (Only "use client" here!)
'use client'; // 👈 Only one small client component!
import { useDolphin, useDolphinClient } from 'dolphin-client/react';
export default function ProductsList({ initialProducts }: { initialProducts: any[] }) {
// Dolphin takes over: auto-syncs WebSocket, cache, offline, mutations!
const { items: products, loading, error } = useDolphin('products', initialProducts);
const dolphin = useDolphinClient();
if (loading) return <div className="spinner">Loading...</div>;
if (error) return <div className="error">Error: {error.message}</div>;
return (
<div className="grid grid-cols-1 md:grid-cols-3 gap-6">
{products.map(product => (
<div key={product.id} className="product-card p-4 border rounded-lg">
<img src={product.image} alt={product.title} className="w-full h-48 object-cover mb-2" />
<h3 className="font-bold">{product.title}</h3>
<p className="text-2xl font-bold text-cyan-500">${product.price}</p>
<button
onClick={() => dolphin.api.post('/api/cart/add', { productId: product.id })}
className="mt-2 bg-blue-500 text-white px-4 py-2 rounded">
Add to Cart
</button>
</div>
))}
</div>
);
}Bonus: Next.js + Dolphin Without React Components! (Pure HTML)
Wait—you don't even need React components! Use Dolphin's declarative HTML directives directly in Next.js Server Components:
// app/shop/page.tsx (100% Server Component!)
export default function ShopPage() {
return (
<div>
<h1>Shop</h1>
{/* Dolphin declarative directives work directly! */}
<input
type="text"
data-store-write="app.search"
placeholder="Search products..."
className="input" />
<div
data-api-get="/api/products"
data-rt-search="title==app.search"
data-rt-template="#product-card">
</div>
<template id="product-card">
<div class="product-card">
<h3>{{title}}</h3>
<p>${{price}}</p>
</div>
</template>
<dolphin-store name="app" search=""></dolphin-store>
{/* Load Dolphin Client at bottom of body */}
<script src="/dolphin-client.js" defer></script>
</div>
);
}Why Next.js + Dolphin is amazing:
- 100% SEO: Server Components render the initial HTML
- Minimal
use client: Only tiny wrapper components if needed - No build step for Dolphin: Use the CDN or static JS file
- Built-in offline/cache/WS: No need for SWR/React Query/TanStack Query
7. JavaScript Store API (Imperative / No React)
Query and filter dynamic database collections programmatically in JS:
const users = dolphin.store.users;
const results = users
.search('admin', ['role', 'name'])
.filter('active', true)
.sort('name', true);
await users.optimisticUpdate(101, { status: 'suspended' }, () =>
dolphin.api.put('/users/101', { status: 'suspended' })
);
dolphin.store.destroy(); // cleanup on SPA unmount9. Perfect for PHP Frameworks (Laravel, WordPress, CodeIgniter, Drupal)
Dolphin Client is tailor-made for PHP backends! No separate JSON API, no build tools, no hydration headaches! Just pure HTML from PHP templates + Dolphin for reactivity!
Example 1: Laravel Blade + Dolphin
<!-- resources/views/products.blade.php -->
@extends('layouts.app')
@section('content')
<h1>Products</h1>
<!-- Declarative search -->
<input
type="text"
data-store-write="app.search"
placeholder="Search products..."
class="form-control">
<!-- Fetch products from Laravel API, search/sort, render template -->
<div
data-api-get="/api/products"
data-rt-search="title==app.search"
data-rt-sort="app.sort"
data-rt-template="#product-card">
<div class="spinner">Loading...</div>
</div>
<!-- Browser-native template tag -->
<template id="product-card">
<div class="product-card">
<img src="{{image}}" alt="{{title}}" class="w-full">
<h3>{{title}}</h3>
<p class="text-2xl font-bold">${{price}}</p>
<button
data-api-click="POST /api/cart/add"
data-api-payload='{"product_id": "{{id}}"}'
class="btn btn-primary">Add to Cart</button>
</div>
</template>
<!-- Initialize store -->
<dolphin-store name="app" search="" sort=""></dolphin-store>
@endsection
<!-- In your layout/app.blade.php, include Dolphin Client! -->
<script src="{{ asset('js/dolphin-client.js') }}"></script>Example 2: WordPress Plugin/Theme + Dolphin
<!-- wp-content/themes/your-theme/single-product.php -->
<?php get_header(); ?>
<div class="container">
<h1><?php the_title(); ?></h1>
<!-- Add to Cart button with Dolphin API call -->
<button
data-api-click="POST <?php echo esc_url(home_url('/wp-json/cart/add')); ?>"
data-api-payload='{"product_id": <?php echo get_the_ID(); ?>}'
class="btn btn-primary">Add to Cart</button>
</div>
<!-- Load Dolphin Client -->
<script src="<?php echo get_template_directory_uri(); ?>/js/dolphin-client.js"></script>
<?php get_footer(); ?>Why PHP + Dolphin is the perfect combo:
- No Separate API Needed: Use your existing PHP endpoints directly
- CSRF Support: Auto-extracts CSRF tokens from Laravel/WordPress forms
- No Build Tools: No Vite/Webpack, no
node_modulesbloat - SEO First: PHP renders the initial HTML, Dolphin adds interactivity
- Works Everywhere: Laravel, CodeIgniter, WordPress, Drupal, Magento, etc.
10. Silent Zero-Configuration Auto-Initialization
When loaded via a standard <script> tag in browser environments, Dolphin Client automatically boots up a default client instance as window.dolphin on DOMContentLoaded.
For debugging, pass data-debug="true" on your script tag to turn on gorgeous, color-coded logging in your developer console for all API calls, WebSocket events, and Store updates:
<script src="js/dolphin-client.js" data-debug="true"></script>License
ISC License
