Skip to content

Latest commit

 

History

1,177 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

aparté

Framework-agnostic AI Chat Web Components. Drop an <aparte-chat> onto any page — React, Vue, Svelte, Angular, or none at all — wire it to any LLM through a pluggable transport, and restyle everything with CSS variables. Zero third-party dependencies at the core. See how it compares with assistant-ui, Deep Chat and Loquix.

CI npm (beta) License: MIT

🚀 Beta on npm. Every @aparte/* package ships together at one version under the beta tag — npm i @aparte/core@beta (the badge above is the live number). The number itself is a plain 0.x: what says beta is the npm tag, the leading zero and this notice — not a -beta suffix. The declared surface is frozen as of 0.17.0 and leaves only through a notice release; what changed when is at apartejs.dev/changelog (or CHANGELOG.md here), and the docs live at apartejs.dev.

pronounced ah-par-té — French aparté: a line spoken aside, a private word taken "in aparté". Also reads as a part: one composable piece.

Why aparté

  • Framework-agnostic core. One engine — vanilla Web Components — renders the same chat everywhere. Thin wrappers give React/Vue/Svelte/Angular an ergonomic component; with no framework, use the <aparte-*> custom elements directly.
  • Zero third-party dependencies in @aparte/core. Markdown, syntax highlighting, model pickers — all opt-in provider-* / plugin-* packages. The core stays tiny.
  • Bring your own model, your way. A transport seam decides where the request goes: AparteDirectTransport (browser-direct — BYOK or a local model) or AparteBackendTransport (your /api/chat, key stays server-side). Providers cover the OpenAI-compatible family, the Vercel AI SDK (25+ vendors), and in-browser Transformers.js.
  • Streaming, typed segments, tools. Replies stream as typed segments — text, markdown, code, chain-of-thought — including a tool_call segment with a built-in human-in-the-loop approve/reject gate.
  • Yours to restyle. Theme everything through CSS variables (no forking), swap icons and render hooks, and localise the UI strings (English built-in, French shipped).
  • A library, not an app. No routing, settings, or persistence baked in, and backend-agnostic — it's a chat surface you compose, not a product you inherit.

Quick start — no framework

npm install @aparte/core @aparte/provider-openai-compat
<aparte-chat center-empty placeholder="Ask anything…" style="height: 600px"></aparte-chat>
import '@aparte/core';                 // registers the <aparte-*> custom elements
import '@aparte/core/styles.css';      // theme variables + component styles
import { registerDefaultRenderers, aparteGlobalConfig, AparteClient, AparteDirectTransport } from '@aparte/core';
import { createOpenAICompatProvider, presets } from '@aparte/provider-openai-compat';

registerDefaultRenderers();

// A local model (LM Studio / Ollama) needs no key — just enable CORS in the app.
// Swap in presets.OPENAI / .MISTRAL / .OPENROUTER (+ a keyResolver) for a cloud vendor.
aparteGlobalConfig.registerAIProvider(createOpenAICompatProvider(presets.LMSTUDIO));
aparteGlobalConfig.setTransport(new AparteDirectTransport({ byok: true }));
new AparteClient().start();            // listens for sends, streams the reply into the chat

// Retry/edit only work with a host like the client above, so core ships them off:
aparteGlobalConfig.setBubbleActions({ retry: true, edit: true });

// The bare shell streams the assistant reply; echo the user's own message in:
const chat = document.querySelector('aparte-chat')!;
chat.addEventListener('aparte-send', (e) =>
  chat.viewport?.appendMessage({ id: crypto.randomUUID(), role: 'user', content: e.detail.content, timestamp: Date.now() }),
);

A real streaming, bring-your-own-key chat — no backend, no build magic. → Getting started

Any framework

Same core, an ergonomic component per framework — and the wrapper owns the state and the user bubble, so there's even less to wire:

npm install @aparte/react @aparte/core react react-dom
import { AparteChat, useAparteChat, useAparteClient } from '@aparte/react';
import { aparteGlobalConfig, AparteDirectTransport } from '@aparte/core';
import { createOpenAICompatProvider, presets } from '@aparte/provider-openai-compat';
import '@aparte/core/styles.css';

aparteGlobalConfig.registerAIProvider(createOpenAICompatProvider(presets.OPENROUTER));
aparteGlobalConfig.setTransport(new AparteDirectTransport({ byok: true }));

export function Chat() {
  const chat = useAparteChat();
  useAparteClient();                   // bridges composer sends to the model
  return <AparteChat ref={chat.ref} messages={chat.messages} onMessagesChange={chat.setMessages} centerWhenEmpty />;
}
Framework Package Guide
React 18 / 19 @aparte/react React
Vue 3 @aparte/vue Vue
Svelte @aparte/svelte Svelte
Angular 19 @aparte/angular Angular

Runnable examples for every framework (plus vanilla) live in apps/examples.

Packages

Package What
@aparte/core Vanilla web components — the chat engine, zero third-party dependencies
@aparte/engine Framework-agnostic agent loop (runStreamAgent)
@aparte/react · /vue · /svelte · /angular Thin, ergonomic framework wrappers (peer deps)
@aparte/provider-openai-compat One adapter for every OpenAI-compatible endpoint (OpenAI, Mistral, OpenRouter, Groq, LM Studio, Ollama…)
@aparte/provider-ai-sdk Vercel AI SDK bridge (Anthropic, Google, 25+ vendors)
@aparte/provider-transformers In-browser inference via Transformers.js
@aparte/provider-scenario A scripted model — replays turns you wrote, for demos, docs and your own tests
@aparte/docs-mcp The docs as an MCP server — npx @aparte/docs-mcp lets your coding agent search and read them
@aparte/plugin-marked · -streaming-markdown · -shiki Markdown rendering + syntax highlighting
@aparte/plugin-model-selector · -ask-user · -approval · -compaction A provider/model picker; a question-elicitation UI; approval modes (plan / ask / auto-edit / auto); conversation compaction
@aparte/locale-fr French UI strings (English is core's built-in default)

Documentation

Live at apartejs.dev — a Starlight site in apps/docs (run pnpm run docs locally):

Status

Beta, built in the open. The core, engine, four wrappers, providers, plugins and six runnable examples are on npm, green across the unit suite and a browser E2E suite (Chromium, WebKit and Firefox, accessibility gated with axe-core). The declared surface is frozen; what is still open before the first stable release is on the roadmap.

Every @aparte/* package is released together, at one version — install any of them at the same number. What shipped when: CHANGELOG.md (the aggregate), or a package's own CHANGELOG.md for its detail.

Contributing

Issues and PRs welcome — see CONTRIBUTING.md for conventions and the gate each change lands behind. It's a pnpm + NX monorepo:

pnpm install
pnpm build        # all packages
pnpm test         # unit suite (Vitest)
pnpm e2e          # browser smoke E2E (Playwright; run pnpm e2e:install once)
pnpm run docs     # the docs site (bare `pnpm docs` triggers npm's builtin instead)

License

MIT © Paul Richez

About

Framework-agnostic AI chat built with Web Components. Streaming, tools, attachments, branching and React/Vue/Svelte/Angular support.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages