13 KiB
13 KiB
| phase | plan | type | wave | depends_on | files_modified | autonomous | requirements | must_haves | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 43-documents-branding | 03 | execute | 3 |
|
|
false |
|
|
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()
**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>