nexus/.planning/phases/43-documents-branding/43-03-PLAN.md

13 KiB

phase plan type wave depends_on files_modified autonomous requirements must_haves
43-documents-branding 03 execute 3
43-01
43-02
ui/src/components/DocumentGeneratePanel.tsx
ui/src/components/BrandKitPanel.tsx
ui/src/components/BrandKitResult.tsx
ui/src/pages/ContentStudio.tsx
false
DOC-01
DOC-02
DOC-03
BRAND-01
BRAND-02
BRAND-03
BRAND-04
BRAND-05
BRAND-06
truths artifacts key_links
User can select document type (report, invoice, one-pager, api-docs) and generate a PDF
Generated PDF can be downloaded from the UI
User can describe a brand and generate a full brand kit
Brand kit result shows logo, avatars, social images, signature, letterhead previews
User can download the entire brand kit as a ZIP file
ContentStudio has Documents and Brand tabs alongside existing tabs
path provides min_lines
ui/src/components/DocumentGeneratePanel.tsx Document type selection, prompt input, PDF generation trigger, download 60
path provides min_lines
ui/src/components/BrandKitPanel.tsx Brand prompt input, generation trigger, result display 50
path provides min_lines
ui/src/components/BrandKitResult.tsx Brand kit display: logo, avatars, social images, templates, guidelines, ZIP download 80
path provides contains
ui/src/pages/ContentStudio.tsx Documents and Brand tabs added documents
from to via pattern
ui/src/components/DocumentGeneratePanel.tsx useContentJob submit('pdf-document', { docType, prompt, title }) pdf-document
from to via pattern
ui/src/components/BrandKitPanel.tsx useContentJob submit('brand-kit', { prompt }) brand-kit
from to via pattern
ui/src/pages/ContentStudio.tsx ui/src/components/DocumentGeneratePanel.tsx import + TabsContent DocumentGeneratePanel
UI panels for document generation and brand kit, wired into ContentStudio tabs.

Purpose: Give users a UI to generate PDFs (reports, invoices, one-pagers, API docs) and complete brand identity kits from a prompt. Adds "Documents" and "Brand" tabs to ContentStudio. Output: DocumentGeneratePanel, BrandKitPanel, BrandKitResult components, updated ContentStudio.

<execution_context> @$HOME/.claude/get-shit-done/workflows/execute-plan.md @$HOME/.claude/get-shit-done/templates/summary.md </execution_context>

@.planning/PROJECT.md @.planning/ROADMAP.md @.planning/STATE.md @.planning/phases/43-documents-branding/43-RESEARCH.md @.planning/phases/43-documents-branding/43-01-SUMMARY.md @.planning/phases/43-documents-branding/43-02-SUMMARY.md

@ui/src/pages/ContentStudio.tsx @ui/src/components/SocialPostPanel.tsx @ui/src/hooks/useContentJob.ts @ui/src/api/contentJobs.ts

From server/src/services/renderers/types.ts (Plan 01):

export interface PdfDocumentBundle {
  type: "pdf-document-bundle";
  docType: string;
  title: string;
  pdfBase64: string;
}

export interface BrandKitBundle {
  type: "brand-kit-bundle";
  spec: { name: string; tagline: string; primaryColor: string; secondaryColor: string; fontStyle: string; industry: string; };
  logoSvgBase64: string;
  avatarPngs: Record<string, string>;      // "512"|"256"|"128"|"64"|"32" -> base64
  socialImages: Record<string, string>;    // "twitter-profile" etc -> base64
  signatureHtml: string;
  letterheadHtml: string;
  guidelinesPdfBase64: string;
  zipBase64: string;
}

From ui/src/hooks/useContentJob.ts:

export function useContentJob(companyId: string): {
  submit: (jobType: string, input: Record<string, unknown>) => void;
  status: string | null;
  bundle: unknown;
  resultAssetId: string | null;
  error: string | null;
};

From ui/src/api/contentJobs.ts:

export function getContentJobAsset(companyId: string, assetId: string): Promise<{ url: string }>;

UI pattern from SocialPostPanel.tsx:

  • useContentJob for submit + SSE progress
  • When status="done" && resultAssetId && !bundle -> fetch asset -> JSON.parse -> setBundle
  • Display result component
  • Download via URL.createObjectURL + .click()
Task 1: Create DocumentGeneratePanel and BrandKitPanel + BrandKitResult components ui/src/components/DocumentGeneratePanel.tsx, ui/src/components/BrandKitPanel.tsx, ui/src/components/BrandKitResult.tsx - ui/src/components/SocialPostPanel.tsx (full file — reference pattern for useContentJob, asset fetch, bundle state, download trigger) - ui/src/components/SocialPostResult.tsx (result display pattern) - ui/src/hooks/useContentJob.ts (hook API) - ui/src/api/contentJobs.ts (getContentJobAsset) - ui/src/components/WallpaperGeneratePanel.tsx (another panel example for download pattern) **DocumentGeneratePanel.tsx:** - Props: `{ companyId: string }` - State: prompt (string), title (string), docType ("report" | "invoice" | "one-pager" | "api-docs"), bundle (PdfDocumentBundle | null) - Define PdfDocumentBundle type locally (same pattern as SocialPostBundle in SocialPostPanel — bundle types are defined locally in panel files per project convention for wallpaper/social, BUT research says to use types.ts for these. Follow research: import is server-side only. Define locally in UI file matching the server shape.) - useContentJob(companyId) for submit + status tracking - UI layout using shadcn Card, CardHeader, CardContent: - Select dropdown for docType with 4 options: Report, Invoice, One-Pager, API Documentation - Input for title - Textarea for prompt/content description - Generate button (disabled when loading, shows Loader2 spinner) - Progress bar when status is "running" or "queued" - When status="done" && resultAssetId && !bundle: fetch asset via getContentJobAsset, parse JSON, setBundle - When bundle exists: show title, docType badge, and a "Download PDF" button - Download PDF: decode pdfBase64 -> Uint8Array -> Blob("application/pdf") -> URL.createObjectURL -> .click() -> revokeObjectURL
**BrandKitPanel.tsx:**
- Props: `{ companyId: string }`
- State: prompt (string), bundle (BrandKitBundle | null)
- Define BrandKitBundle type locally (matching server shape)
- useContentJob(companyId) for submit + status
- UI layout:
  - Textarea for brand description prompt (placeholder: "Describe the brand you want to create -- name, industry, style preferences, colors...")
  - Generate button with loading state
  - Progress bar during generation
- When done: fetch asset, parse JSON, setBundle, render BrandKitResult

**BrandKitResult.tsx:**
- Props: `{ bundle: BrandKitBundle }`
- Display in a grid layout:
  - **Logo section**: SVG preview via `<img src="data:image/svg+xml;base64,{logoSvgBase64}" />`
  - **Avatars section**: Grid of 5 avatar sizes as `<img src="data:image/png;base64,{avatarPngs[size]}" />` with size labels
  - **Social images section**: Grid of social platform images with platform name labels
  - **Templates section**: "Email Signature" and "Letterhead" cards with HTML preview in sandboxed iframes (`srcdoc={signatureHtml}`)
  - **Guidelines**: "Brand Guidelines" card with a "Download PDF" button (decode guidelinesPdfBase64 -> blob download)
  - **Full Kit Download**: Prominent "Download Brand Kit (ZIP)" button at the bottom
- ZIP download function: same base64-to-blob pattern but with type "application/zip" and `.zip` extension (use the downloadZip pattern from RESEARCH.md)
- PDF download for guidelines: same base64-to-blob pattern with type "application/pdf"

Use shadcn components: Card, CardHeader, CardTitle, CardContent, Button, Textarea, Select, SelectContent, SelectItem, SelectTrigger, SelectValue, Progress. Import Loader2 from lucide-react.
- grep -q "DocumentGeneratePanel" ui/src/components/DocumentGeneratePanel.tsx - grep -q "pdf-document" ui/src/components/DocumentGeneratePanel.tsx - grep -q "BrandKitPanel" ui/src/components/BrandKitPanel.tsx - grep -q "brand-kit" ui/src/components/BrandKitPanel.tsx - grep -q "BrandKitResult" ui/src/components/BrandKitResult.tsx - grep -q "zipBase64" ui/src/components/BrandKitResult.tsx - grep -q "Download Brand Kit" ui/src/components/BrandKitResult.tsx pnpm --filter @paperclipai/ui exec tsc --noEmit Document and brand kit panels render with correct form inputs, submit correct job types, display results, and provide download functionality for PDF and ZIP. Task 2: Add Documents and Brand tabs to ContentStudio ui/src/pages/ContentStudio.tsx - ui/src/pages/ContentStudio.tsx (current tab structure — 5 tabs: diagrams, icons, themes, wallpapers, social) 1. Add imports at the top of ContentStudio.tsx: ```typescript import { DocumentGeneratePanel } from "../components/DocumentGeneratePanel"; import { BrandKitPanel } from "../components/BrandKitPanel"; ```
2. Add two new TabsTrigger entries in the TabsList, AFTER the "Social" trigger:
```tsx
<TabsTrigger value="documents">Documents</TabsTrigger>
<TabsTrigger value="brand">Brand</TabsTrigger>
```

3. Add two new TabsContent blocks after the social TabsContent:
```tsx
<TabsContent value="documents" className="mt-4">
  {companyId ? (
    <DocumentGeneratePanel companyId={companyId} />
  ) : (
    <p className="text-sm text-muted-foreground">Select a company to get started.</p>
  )}
</TabsContent>

<TabsContent value="brand" className="mt-4">
  {companyId ? (
    <BrandKitPanel companyId={companyId} />
  ) : (
    <p className="text-sm text-muted-foreground">Select a company to get started.</p>
  )}
</TabsContent>
```

Keep `defaultValue="diagrams"` unchanged. Use stable string values "documents" and "brand" for tab IDs.
- grep -q "DocumentGeneratePanel" ui/src/pages/ContentStudio.tsx - grep -q "BrandKitPanel" ui/src/pages/ContentStudio.tsx - grep -q '"documents"' ui/src/pages/ContentStudio.tsx - grep -q '"brand"' ui/src/pages/ContentStudio.tsx pnpm --filter @paperclipai/ui exec tsc --noEmit ContentStudio has 7 tabs: Diagrams, Icons, Themes, Wallpapers, Social, Documents, Brand. TypeScript compiles cleanly. Task 3: Visual verification of Documents and Brand tabs ui/src/pages/ContentStudio.tsx Human verifies the complete document generation and brand kit UI end-to-end.
How to verify:
1. Navigate to Content Studio in the Nexus UI
2. Verify 7 tabs visible: Diagrams, Icons, Themes, Wallpapers, Social, Documents, Brand
3. Click "Documents" tab:
   - Select "Report" from dropdown
   - Enter a title and prompt
   - Click Generate — verify spinner/progress appears
   - When done, verify "Download PDF" button appears
4. Click "Brand" tab:
   - Enter a brand description
   - Click Generate — verify progress appears
   - When done, verify logo SVG preview, avatar grid, social images, template previews, and "Download Brand Kit (ZIP)" button
5. Download the ZIP — verify it contains logo/, social/, templates/, guidelines.pdf

Resume signal: Type "approved" or describe issues.
pnpm --filter @paperclipai/ui exec tsc --noEmit User confirms Documents and Brand tabs work end-to-end: PDF generation + download, brand kit generation + preview + ZIP download. - `pnpm --filter @paperclipai/ui exec tsc --noEmit` compiles without errors - ContentStudio renders 7 tabs - Document generation flow works end-to-end - Brand kit generation shows all asset previews and ZIP download

<success_criteria>

  • Documents tab: user can select type, enter prompt, generate PDF, download it
  • Brand tab: user can enter description, generate full brand kit, see all previews, download ZIP
  • All 7 ContentStudio tabs render correctly
  • TypeScript clean </success_criteria>
After completion, create `.planning/phases/43-documents-branding/43-03-SUMMARY.md`