Angular
@aparte/angular wraps @aparte/core for Angular 19: an ergonomic <aparte-chat> standalone
component, services for the client and conversations, and a generic <aparte-ui> escape hatch.
npm install @aparte/angular @aparte/core @angular/core @angular/common rxjs@aparte/core, @angular/core, @angular/common and rxjs are peer dependencies.
<aparte-chat>
Section titled “<aparte-chat>”The components are standalone — import them directly, no NgModule:
import { Component } from '@angular/core';import { AparteChatComponent, type AparteMessage } from '@aparte/angular';import '@aparte/core/styles.css';
@Component({ standalone: true, imports: [AparteChatComponent], template: ` <aparte-chat centerWhenEmpty (messagesChange)="messages = $event"> <p slot="empty-state">Ask me anything…</p> </aparte-chat> `,})export class Chat { // The chat owns its thread. Observe it via (messagesChange) — do NOT push it // back through [messages]: the user's message is appended for you on send, so // re-adding it in a (messageSent) handler double-counts it. messages: AparteMessage[] = [];}Slots are content projection by attribute: [slot='empty-state'], [slot='composer'],
[slot='above-composer'], [slot='footer-left'|'footer-center'|'footer-right']. For a fully custom
bubble, pass a template instead:
<aparte-chat [messages]="messages" [bubbleTemplate]="tpl"></aparte-chat><ng-template #tpl let-message> <div class="my-bubble">{{ message.content }}</div></ng-template>Outputs: messageSent, messagesChange, messageAppended, action, typingChange,
conversationCreated. The imperative API (streaming, branch/edit, scrollToBottom,
getViewport) is on the component instance — grab it with a @ViewChild. injectTokenStream
takes the cross-wrapper AsyncIterable<string> — the exact call that works on React/Vue/Svelte —
or an RxJS Observable<string> (the Angular-idiomatic shape); everything else mirrors the
other wrappers.
Wiring a real model
Section titled “Wiring a real model”The wrapper is provider-agnostic. provideAparte() registers your providers and client options
at bootstrap and starts the client (autoConnect, on by default) — composer sends stream
replies with zero extra wiring:
import { bootstrapApplication } from '@angular/platform-browser';import { DirectTransport, AparteConfig } from '@aparte/core';import { createOpenAICompatProvider, presets } from '@aparte/provider-openai-compat';import { provideAparte } from '@aparte/angular';
AparteConfig.setTransport(new DirectTransport({ byok: true }));
bootstrapApplication(App, { providers: [ provideAparte({ providers: [createOpenAICompatProvider(presets.OPENROUTER)], clientOptions: { /* AparteClientOptions */ }, }), ],});That’s it — no lifecycle wiring in your components. To own the client lifecycle yourself, pass
autoConnect: false and use the service:
// only with autoConnect: false — the manual escape hatchimport { inject } from '@angular/core';import { AparteAiService } from '@aparte/angular';
export class Chat { private ai = inject(AparteAiService); ngOnInit() { this.ai.connect(); } // idempotent — safe even if already connected ngOnDestroy() { this.ai.disconnect(); }}provideAparte() is config sugar and fully optional — the components work without it, and you
can call AparteConfig.* directly exactly like the React/Vue/Svelte wrappers do. Its plugins slots
take objects or loader functions you supply, and locale takes an AparteLocale object (e.g.
locale: fr from @aparte/locale-fr) — none of them take package-name strings — so this package
stays a leaf with no plugin catalog. Pass a per-instance [config] to scope providers/transport to a
single <aparte-chat> instead of the global AparteConfig.
Any element: <aparte-ui>
Section titled “Any element: <aparte-ui>”For an <aparte-*> element without a dedicated component, mount it generically. It forwards the
interactive aparté events by default; pass [events] to listen to others:
<aparte-ui name="aparte-model-selector" [props]="{ placeholder: 'Ask…', '--glow-speed': '4s' }" (elementEvent)="onEvent($event)"/>Also exported
Section titled “Also exported”ConversationManagerService— signal-based view over the coreConversationManager(list / create / archive), for a multi-conversation sidebar.