Headless & theming
Keep the behaviour, bring your own markup. Or keep the markup and just move the colours.
All documentation
Getting started
Overview Quickstart SDK packagesFrontend
React Vue Svelte React Native Web Components Headless & theming Real-timeBackend API
Authentication Templates Trigger & status Contacts & preferencesMore
Self-hosting ReferenceBring your own UI
Every packaged component is built on hooks and stores you can use directly. For a framework we don't ship yet, or a design system that will not tolerate someone else's markup, drop to @elaanio/core, the same observable stores every binding is built on:
import { ElaanClient, createInboxStore } from "@elaanio/core"; const client = new ElaanClient("https://api.elaan.io/v1", tokenProvider); const inbox = createInboxStore(client, { pollInterval: 30000 }); inbox.subscribe(() => render(inbox.getState())); // getState() / getUnreadCount() inbox.markRead(id); // + markAllRead / remove / refresh
You give up the components and keep everything else: token refresh, realtime with polling fallback, optimistic updates, and reconciliation after a dropped connection. That is the part worth not rewriting.
Theming
If you only want to restyle rather than replace, the web components (React, Vue, Web Components) are styled entirely with CSS custom properties. Override them on :root; light and dark are automatic via prefers-color-scheme.
/* your global stylesheet */
:root {
--elaan-accent: #7c3aed;
--elaan-radius: 6px;
--elaan-bg: #fff;
--elaan-text: #1a1d23;
}
Full tokens: --elaan-accent, --elaan-accent-ink, --elaan-bg, --elaan-bg-hover, --elaan-text, --elaan-muted, --elaan-border, --elaan-danger, --elaan-radius, --elaan-shadow.
Which layer to use
- Components (
@elaanio/react,/vue,/react-native,/elements) when the default UI is close enough and CSS tokens close the gap. - Hooks and composables (
@elaanio/react-core, or the ones re-exported by each binding) when you want the behaviour and your own markup. - Core stores (
@elaanio/core) when you are on a framework we don't ship, or building something that is not a list at all.