Files
ClaudeMarketing/prisma/schema.prisma
T
Trey t 2ab8af64d4 feat: add variation spawner and content repurposing
Variation spawner: select an image asset → spawn N variations that keep the
same emotional pattern/visual style but explore different hook angles. Runs
a focused ad-creative-designer agent with the original as a Gemini reference
image. New assets link back via parentAssetId.

Content repurposing: resize an image to all other platform dimensions using
Sharp (cover crop). Captions are re-toned for the target platform via Claude
CLI. No external APIs needed — fully local.

- Add parentAssetId self-relation to Asset model
- lib/repurpose.ts: Sharp resize, platform format mapping, caption re-toning
- lib/variations.ts: asset DNA extraction, variation prompt builder, mini-pipeline
- API routes: /api/assets/[id]/repurpose (GET formats, POST resize)
- API routes: /api/assets/[id]/variations (GET existing, POST spawn)
- Repurpose modal: checkbox list of target formats
- Variation modal: count picker, async launch
- Asset card: Repurpose + Variations buttons on image assets
- Asset lineage: "Derived from" shown on child assets

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-23 22:46:42 -05:00

115 lines
3.5 KiB
Plaintext

generator client {
provider = "prisma-client"
output = "../lib/generated/prisma"
}
datasource db {
provider = "sqlite"
}
model User {
id String @id @default(cuid())
email String @unique
password String
name String?
createdAt DateTime @default(now())
}
model App {
id String @id @default(cuid())
name String
slug String @unique
description String?
primaryColor String @default("#0079FF")
accentColor String @default("#FF9400")
darkBg String @default("#1a1a2e")
appUrl String?
brandIdentity String?
productInfo String?
platformGuidelines String?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
campaigns Campaign[]
}
model Campaign {
id String @id @default(cuid())
name String
status String @default("draft") // draft, running, review, approved, published
prompt String?
platforms String // JSON array: ["instagram","tiktok","nextdoor"]
config String? // JSON: full campaign config from form
outputPath String?
appId String?
app App? @relation(fields: [appId], references: [id])
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
agentRuns AgentRun[]
assets Asset[]
claudeSessions ClaudeSession[]
}
model AgentRun {
id String @id @default(cuid())
campaignId String
campaign Campaign @relation(fields: [campaignId], references: [id])
agentName String
status String @default("pending") // pending, running, completed, failed
startedAt DateTime?
completedAt DateTime?
durationMs Int?
outputSummary String?
outputPath String?
tokenUsage Int?
error String?
assets Asset[]
createdAt DateTime @default(now())
}
model Asset {
id String @id @default(cuid())
campaignId String
campaign Campaign @relation(fields: [campaignId], references: [id])
agentRunId String?
agentRun AgentRun? @relation(fields: [agentRunId], references: [id])
type String // image, video, copy, research, script
platform String? // instagram, tiktok, nextdoor, all
format String? // png, mp4, json, txt, html, md
filePath String
fileName String
dimensions String? // 1080x1080, 1080x1920, etc.
metadata String? // JSON: caption, hashtags, hook text, scene plan
status String @default("draft") // draft, approved, rejected, published
publishedTo String? // JSON array of platforms published to
postizPostId String?
postizMediaId String?
parentAssetId String?
parentAsset Asset? @relation("AssetVariations", fields: [parentAssetId], references: [id])
variations Asset[] @relation("AssetVariations")
createdAt DateTime @default(now())
}
model ClaudeSession {
id String @id @default(cuid())
campaignId String
campaign Campaign @relation(fields: [campaignId], references: [id])
sessionId String?
messages String? // JSON array of conversation history
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
model TrendReport {
id String @id @default(cuid())
name String
filePath String
summary String?
createdAt DateTime @default(now())
}
model Setting {
key String @id
value String
updatedAt DateTime @updatedAt
}