@creaditor/cdtr-series-newsletter
v0.1.2
Published
Embeddable <cdtr-series-newsletter> web component. AI chat-driven email series builder with outline review, newsletter generation, and preview. Hebrew + English.
Maintainers
Readme
@creaditor/cdtr-series-newsletter
Embeddable <cdtr-series-newsletter> web component. An AI chat-driven email series builder: the user describes what they want in a conversation, the component generates a series outline they can review and edit, renders each newsletter, and previews the result. Hebrew + English out of the box, with full RTL layout.
Built with Lit. The component owns the whole UI flow (chat → outline → generation → preview); the host page owns the backend — you point it at an API base URL and Creaditor drives the rest.
How it works
The component walks the user through four phases:
- Chat — the user talks to an assistant (rendered via
<cdtr-chat>) that extracts the series goal, email count, title, and audience. When enough is known, it offers to build the outline. - Outline — the AI proposes a card per email (subject, summary, send-offset in days). The user can edit, reorder timing, delete, or ask the AI to rewrite any card.
- Generating — each approved card is turned into a full newsletter, one at a time, with per-email retry on failure.
- Preview — the rendered newsletters are shown. On approval the component emits a single event with the final prompts and generated newsletter JSON.
Install
npm install @creaditor/cdtr-series-newsletterUse
Dependency: the component renders
<cdtr-chat>inside its shadow DOM but does not bundle it. You must load@creaditor/cdtr-chatbefore this component, or the chat phase renders blank.
As an ES module
<cdtr-series-newsletter
lang="en"
user-name="Alex"
api-url="https://your-backend.example.com/api/series"
studio-token="<JWT>"
style="display:block; height: 80vh; max-width: 720px;"
></cdtr-series-newsletter>
<script type="module">
import '@creaditor/cdtr-chat'; // must come first
import '@creaditor/cdtr-series-newsletter';
const el = document.querySelector('cdtr-series-newsletter');
// Fired once, when the user approves the previewed series.
el.addEventListener('cdtr-series-newsletter:approved', (e) => {
const { prompts, newsletters } = e.detail;
// prompts → one { type, prompt, sendOffsetDays } per email
// newsletters → the generated Creaditor newsletter JSON per email
myApp.scheduleSeries(prompts, newsletters);
});
</script>Via CDN (UMD)
<script src="https://unpkg.com/@creaditor/cdtr-chat"></script>
<script src="https://unpkg.com/@creaditor/cdtr-series-newsletter"></script>
<cdtr-series-newsletter
api-url="https://your-backend.example.com/api/series"
></cdtr-series-newsletter>Sizing
The component fills its host. Give the element (or a wrapper) an explicit height, e.g. style="display:block; height: 80vh;", otherwise the chat area collapses.
Attributes
| Attribute | Type | Default | Description |
| ----------------- | ------ | ------- | ------------------------------------------------------------------------------------------------- |
| lang | string | "en" | "he" or "en". Auto-sets dir="rtl" for Hebrew. |
| user-name | string | "" | Personalizes the assistant's greeting and is sent to the /chat endpoint. |
| api-url | string | "" | Required. Base URL for the backend. The component appends /chat, /generate-cards, etc. |
| studio-token | string | "" | Bearer JWT sent as Authorization: Bearer <token> on every API call. Omit for open/dev backends. |
| token-balance | number | null | If set, renders a token-balance chip. Below ~40k shows a "buy" link; below ~1k reads as empty. |
| payment-url | string | "" | Link target for the "buy tokens" chip (used with token-balance). |
| error-token-img | string | "" | Optional image shown on the "out of tokens" error screen. |
All attributes can also be set as properties (e.g. el.tokenBalance = 25000).
Events
Bubbles and composed. Prefixed with cdtr-series-newsletter:.
| Event | detail | When |
| ------------------------------ | --------------------------- | ---------------------------------------------------------- |
| cdtr-series-newsletter:approved | { prompts, newsletters } | User approved the previewed series (the terminal action). |
// detail shape
{
prompts: Array<{
type: 'authentic';
prompt: string; // "Subject: …\n\n<summary>"
sendOffsetDays: number; // 0 = same day, 1 = next day, …
}>;
newsletters: unknown[]; // generated Creaditor newsletter JSON, one per prompt (null if that email failed)
}Backend contract
Set api-url to a base path; the component calls these routes beneath it. Each request carries Authorization: Bearer <studio-token> when the token attribute is set, and language reflects the lang attribute.
| Route | Request body | Expected response |
| ---------------------- | ------------------------------------------------------- | ------------------------------------------------------------------------ |
| POST /chat | { messages, language, userName } | { reply, extracted?: {goal,count,title,audience}, ready?: boolean } |
| POST /generate-cards | { goal, count, title, audience, language } | { cards: [{ subject, summary, sendOffsetDays }] } |
| POST /assist-card | { instruction, card, seriesContext, language } | { subject?, summary? } (the rewritten card) |
| POST /generate-newsletter | { prompt, language } | Creaditor newsletter JSON for one email |
messagesis the running[{ role, content }]history.ready: trueon/chatunlocks the "build outline" step.- Return HTTP
429with{ error: "token_balance_exceeded", paymentUrl? }to trigger the built-in out-of-tokens screen. - On
/chaterrors, an{ reason }field is surfaced to the user; other routes fall back to a generic error.
Types
import type { OutlineCard } from '@creaditor/cdtr-series-newsletter';
type OutlineCard = {
id: string;
subject: string;
summary: string;
sendOffsetDays: number; // days after the first email
};The i18n helpers are also exported: STRINGS, isRtl, t, and the Lang type.
Styling
The component exposes CSS custom properties for theming (set them on the element or a parent):
cdtr-series-newsletter {
--cdtr-sn-bg: #ffffff;
--cdtr-sn-surface: #faf9fc;
--cdtr-sn-fg: #17161d;
--cdtr-sn-fg-secondary: #6c6b78;
--cdtr-sn-accent: #6328A7;
--cdtr-sn-accent-gradient: linear-gradient(135deg, #A8107E, #6328A7);
--cdtr-sn-border: #ececef;
--cdtr-sn-danger: #e11d48;
--cdtr-sn-radius: 16px;
--cdtr-sn-font: 'Rubik', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
}The component uses the Rubik font; load it on the host page for the intended look:
<link href="https://fonts.googleapis.com/css2?family=Rubik:wght@300;400;500;600;700&display=swap" rel="stylesheet" />Local development
npm install
npm run dev # Vite dev server on http://localhost:5173
npm run build # emits ES + UMD bundles and types to dist/index.html is a working harness that loads <cdtr-chat>, mints a dev studio token, points at a local backend (http://localhost:8000/api/series), and logs emitted events.
License
MIT
