Your first component
Tutorial de cinco minutos: construa uma chat surface funcional a partir de três primitives.
Este tutorial conecta três primitives de AI do Gremorie -- PromptInput,
Conversation e Message -- em uma chat surface funcional. Você vai
terminar com uma UI que aceita um prompt, exibe a mensagem do usuário e
faz streaming da resposta de um modelo.
Esta é a composição carro-chefe do Gremorie. Os mesmos três primitives alimentam o block de chat surface planejado em Blocks.
Objetivo
Uma chat surface onde:
- O usuário digita um prompt e o submete
- A mensagem do usuário renderiza na conversation
- Uma mensagem de AI faz streaming de volta como resposta
De ponta a ponta, em cinco minutos.
Passos
Adicione os primitives
npx gremorie@latest add ng-prompt-input ng-conversation ng-messagenpx gremorie@latest add rx-prompt-input rx-conversation rx-messageA CLI resolve as dependências cruzadas entre itens (cada primitive depende de
*-core para os tokens e o utilitário cn), puxa elas também, e escreve
tudo em src/components/gremorie/.
Componha a surface
import { Component, signal } from '@angular/core';
import { NgConversation } from '@/components/gremorie/ng-conversation';
import { NgMessage } from '@/components/gremorie/ng-message';
import { NgPromptInput } from '@/components/gremorie/ng-prompt-input';
interface Msg {
role: 'user' | 'assistant';
content: string;
}
@Component({
standalone: true,
imports: [NgConversation, NgMessage, NgPromptInput],
template: `
<ng-conversation>
@for (m of messages(); track $index) {
<ng-message [role]="m.role">{{ m.content }}</ng-message>
}
</ng-conversation>
<ng-prompt-input (submit)="onSubmit($event)" />
`,
})
export class ChatComponent {
messages = signal<Msg[]>([]);
onSubmit(text: string) {
this.messages.update((m) => [...m, { role: 'user', content: text }]);
// wire your backend here
}
}'use client';
import { useState } from 'react';
import { Conversation } from '@/components/gremorie/rx-conversation';
import { Message } from '@/components/gremorie/rx-message';
import { PromptInput } from '@/components/gremorie/rx-prompt-input';
type Msg = { role: 'user' | 'assistant'; content: string };
export function Chat() {
const [messages, setMessages] = useState<Msg[]>([]);
return (
<>
<Conversation>
{messages.map((m, i) => (
<Message key={i} role={m.role}>
{m.content}
</Message>
))}
</Conversation>
<PromptInput
onSubmit={(text) => {
setMessages((prev) => [...prev, { role: 'user', content: text }]);
// wire your backend here
}}
/>
</>
);
}Conecte um backend
Os primitives são agnósticos de transporte. Conecte-os ao que você usar: o AI SDK, uma Server Action, um endpoint de streaming próprio seu.
// Minimal handler -- replace with your real model call
async function handleSubmit(text: string) {
setMessages((prev) => [...prev, { role: 'user', content: text }]);
const response = await fetch('/api/chat', {
method: 'POST',
body: JSON.stringify({ message: text }),
});
const data = await response.json();
setMessages((prev) => [...prev, { role: 'assistant', content: data.reply }]);
}Para respostas com streaming, troque o fetch por um streaming reader e
anexe os tokens à mensagem do assistant conforme eles chegam.
Rode
nx serve my-apppnpm devAbra a página, digite um prompt, aperte Enter. O balão do usuário cai na conversation, seu backend responde, o balão do assistant se junta a ele.
Veja a conexão completa no Assistant block -- ele empacota um SDK de streaming, attachments e renderização de tool-calls.
O que você aprendeu
- Primitives instalam como source via a CLI
- Composição sobre configuração: três componentes pequenos formam uma surface
- O mesmo formato funciona em Angular e React porque o registry é a fonte da verdade
Em seguida, veja Project setup para configuração avançada (path aliases, troca de tema, overrides de token custom).