Skip to main content

Getting Started

This guide walks you through installing Synapse UI in an Angular application and using the MVP components.

Status: The npm packages and Nx workspace are not yet scaffolded. This guide describes the intended consumer experience. Track implementation progress in PROGRESS.md.

Prerequisites

  • Node.js ^20.19.0
  • Angular 21.x (latest stable)
  • npm 9.x+

Installation

Install the MVP packages:

npm install @synapse-ui/theme @synapse-ui/ai-prompt @synapse-ui/stream-container
npm install marked shiki

Configure Theming

Add the theme provider to your application config:

// app.config.ts
import { ApplicationConfig } from '@angular/core';
import { provideSynapseTheme } from '@synapse-ui/theme';

export const appConfig: ApplicationConfig = {
providers: [
provideSynapseTheme({
defaultTheme: 'light',
persist: true,
}),
],
};

Import the base token stylesheet in angular.json or styles.css:

@import '@synapse-ui/theme/tokens.css';

Build a Chat Interface

1. Template

<!-- chat.component.html -->
<div class="chat-layout">
<synapse-ai-stream-container
[content]="response()"
[streaming]="isStreaming()"
/>

<synapse-ai-prompt-bar
[loading]="isStreaming()"
(submit)="sendPrompt($event)"
(stopGeneration)="stopStream()"
/>
</div>

2. Component

import { Component, signal, inject, DestroyRef } from '@angular/core';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { AiPromptBarComponent, PromptSubmitEvent } from '@synapse-ui/ai-prompt';
import { AiStreamContainerComponent } from '@synapse-ui/stream-container';

@Component({
selector: 'app-chat',
standalone: true,
imports: [AiPromptBarComponent, AiStreamContainerComponent],
templateUrl: './chat.component.html',
styleUrl: './chat.component.css',
})
export class ChatComponent {
private destroyRef = inject(DestroyRef);
private abortController: AbortController | null = null;

response = signal('');
isStreaming = signal(false);

sendPrompt(event: PromptSubmitEvent): void {
this.response.set('');
this.isStreaming.set(true);
this.abortController = new AbortController();

// Example: connect to your SSE backend
const source = new EventSource(`/api/chat?prompt=${encodeURIComponent(event.text)}`);

source.onmessage = (e) => {
this.response.update((prev) => prev + e.data);
};

source.onerror = () => {
source.close();
this.isStreaming.set(false);
};
}

stopStream(): void {
this.abortController?.abort();
this.isStreaming.set(false);
}
}

3. Styles

Use theme tokens — no hardcoded colors:

.chat-layout {
display: flex;
flex-direction: column;
gap: var(--synapse-spacing-4);
max-width: 48rem;
margin: 0 auto;
padding: var(--synapse-spacing-6);
background: var(--synapse-surface-primary);
min-height: 100vh;
}

Theme Switching

import { ThemeService } from '@synapse-ui/theme';

// In a settings component
themeService.setTheme('dark');

See ThemeService for the full API.

Next Steps

TopicDoc
Component APIsComponents
ArchitectureOverview
Create your own componentCreating a Component
Publish packagesPublishing
ContributeCONTRIBUTING.md

Troubleshooting

Styles look unstyled / no colors

Ensure @synapse-ui/theme/tokens.css is imported and provideSynapseTheme() is in your app config.

Stream container not updating

Verify you are updating the content signal/input on each SSE chunk and that streaming is true during active streams.

Shiki highlighting slow on first render

Shiki loads grammars lazily. Pre-load common languages in app bootstrap if needed (documented in Phase 2 implementation).