diff --git a/docs/6-5-pptx-export-watermark.md b/docs/6-5-pptx-export-watermark.md new file mode 100644 index 0000000..1f5f75e --- /dev/null +++ b/docs/6-5-pptx-export-watermark.md @@ -0,0 +1,50 @@ +# Story 6-5 — PPTX Export Watermark (PLG Viral Loop) + +**Epic:** 6 — Croissance & Activation (PLG) +**Status:** done + +## User Story + +**En tant qu'** utilisateur qui partage une présentation exportée depuis Memento, +**Je veux** que chaque slide porte discrètement la mention "memento-note.com", +**Afin que** les destinataires découvrent l'outil et s'inscrivent (boucle virale PLG). + +## Acceptance Criteria + +- [x] **AC-1** : Chaque slide du PPTX brainstorm contient "memento-note.com" en bas-droite +- [x] **AC-2** : Chaque slide du PPTX IA (generate_pptx) contient "memento-note.com" en bas-droite +- [x] **AC-3** : Le watermark est subtil (7pt, gris clair `#B8B0A8`, italique) — visible mais non intrusif +- [x] **AC-4** : Zéro régression sur la mise en page existante des slides + +## Tasks + +- [x] T1 — Ajouter helper `addWatermark(slide)` + `withWatermark(pres)` dans `lib/brainstorm/export-pptx.ts` +- [x] T2 — Appliquer `withWatermark` dans `generateBrainstormPptx` (monkey-patch `pres.addSlide`) +- [x] T3 — Ajouter helper `addWatermark(slide)` + `withWatermark(pres)` dans `lib/ai/tools/pptx.tool.ts` +- [x] T4 — Appliquer `withWatermark` dans `buildPresentation` (monkey-patch `pres.addSlide`) +- [x] T5 — Vérifier TypeScript + 174 tests unitaires passent + +## Files Modified + +- `memento-note/lib/brainstorm/export-pptx.ts` — helpers `addWatermark` + `withWatermark`, monkey-patch dans `generateBrainstormPptx` +- `memento-note/lib/ai/tools/pptx.tool.ts` — helpers `addWatermark` + `withWatermark`, monkey-patch dans `buildPresentation` + +## Technical Notes + +**Pattern monkey-patch :** +```ts +function withWatermark(pres: PptxGenJSModule): PptxGenJSModule { + const original = pres.addSlide.bind(pres) + ;(pres as any).addSlide = (...args: any[]) => { + const slide = original(...args) + addWatermark(slide) + return slide + } + return pres +} +``` +Ce pattern garantit que le watermark est ajouté sur **toutes** les slides sans modifier les 14+ fonctions de construction de slides. + +**Design watermark :** +- Position : `x: 7.0, y: 5.35, w: 2.7, h: 0.2` (bas-droite, slide 10"×5.63") +- Style : 7pt Arial, couleur `B8B0A8`, italique, alignement droite diff --git a/docs/sprint-status.yaml b/docs/sprint-status.yaml index 9afd826..aa1ee9e 100644 --- a/docs/sprint-status.yaml +++ b/docs/sprint-status.yaml @@ -66,8 +66,8 @@ development_status: 6-1-onboarding-activation: done # story-onboarding-activation.md 6-2-markdown-roundtrip: review # brief-markdown-roundtrip.md 6-3-brainstorm-canvas-finalize: review # story: 6-3-brainstorm-canvas-finalize.md - 6-4-chat-with-pdf: backlog - 6-5-pptx-export-watermark: backlog + 6-4-chat-with-pdf: done # already implemented: document-qa-overlay.tsx + document-ingestion + document-search tool + 6-5-pptx-export-watermark: done # story: 6-5-pptx-export-watermark.md epic-6-retrospective: optional diff --git a/memento-note/lib/ai/tools/pptx.tool.ts b/memento-note/lib/ai/tools/pptx.tool.ts index 1260d93..4389c37 100644 --- a/memento-note/lib/ai/tools/pptx.tool.ts +++ b/memento-note/lib/ai/tools/pptx.tool.ts @@ -105,6 +105,26 @@ const SHAPE_RECT = 'rect' as const const SHAPE_ROUND_RECT = 'roundRect' as const const SHAPE_OVAL = 'ellipse' as const +/** PLG viral watermark injected on every slide automatically */ +function addWatermark(slide: any) { + slide.addText('memento-note.com', { + x: 7.0, y: 5.35, w: 2.7, h: 0.2, + fontSize: 7, fontFace: 'Arial', color: 'B8B0A8', + align: 'right', italic: true, + }) +} + +/** Wrap pres.addSlide so every new slide gets the Momento watermark automatically */ +function withWatermark(pres: PptxGenJSModule): PptxGenJSModule { + const original = pres.addSlide.bind(pres) + ;(pres as any).addSlide = (...args: any[]) => { + const slide = original(...args) + addWatermark(slide) + return slide + } + return pres +} + function addBadge(s: any, num: number, accent: string) { s.addShape(SHAPE_OVAL, { x: 9.3, y: 5.1, w: 0.4, h: 0.4, @@ -978,7 +998,7 @@ async function buildPresentation(spec: PresentationSpec): Promise max ? text.slice(0, max - 1) + '…' : text } +/** + * PLG viral watermark — added to every slide automatically via addSlide monkey-patch. + * Subtle branding in bottom-right corner to drive organic acquisition. + */ +function addWatermark(slide: any) { + slide.addText('memento-note.com', { + x: 7.0, y: 5.35, w: 2.7, h: 0.2, + fontSize: 7, fontFace: 'Arial', color: 'B8B0A8', + align: 'right', italic: true, + }) +} + +/** Wrap pres.addSlide so every new slide gets the Momento watermark automatically */ +function withWatermark(pres: PptxGenJSModule): PptxGenJSModule { + const original = pres.addSlide.bind(pres) + ;(pres as any).addSlide = (...args: any[]) => { + const slide = original(...args) + addWatermark(slide) + return slide + } + return pres +} + // Add a consistent slide background function addBg(slide: any) { slide.background = { color: T.bg } @@ -279,7 +302,7 @@ function buildSummarySlide(pres: PptxGenJSModule, session: SessionLike, stats: { export async function generateBrainstormPptx(session: SessionLike): Promise<{ buffer: Buffer; filename: string }> { const PptxGenJS = await getPptxGenClass() - const pres = new PptxGenJS() + const pres = withWatermark(new PptxGenJS()) pres.layout = 'LAYOUT_WIDE' pres.author = 'Momento'