Project Brief
atroui/project-briefFreeUtility
Shared ProjectBrief type + OG/thumbnail href helpers for Scope → Planner → social card glue.
Install it
npx shadcn@latest add https://atroui.com/r/project-brief.jsonSource
1/**2 * Shared launch brief — glue between Scope → Planner → OG / Thumbnail.3 * Host-owned, serializable JSON. No AtroUI backend required.4 *5 * Install: npx shadcn@latest add @atroui/project-brief6 */78export type ProjectBrief = {9 name: string10 oneLiner: string11 audience: string12 pages: string[]13 tone: string14 constraints: string[]15 ogTitle?: string16 ogSubtitle?: string17 thumbnailTitle?: string18}1920export const EMPTY_PROJECT_BRIEF: ProjectBrief = {21 name: "",22 oneLiner: "",23 audience: "",24 pages: [],25 tone: "",26 constraints: [],27}2829/** localStorage key for optional client-side persistence on the host. */30export const PROJECT_BRIEF_STORAGE_KEY = "atroui:project-brief"3132export function isProjectBrief(value: unknown): value is ProjectBrief {33 if (!value || typeof value !== "object") return false34 const v = value as Record<string, unknown>35 return (36 typeof v.name === "string" &&37 typeof v.oneLiner === "string" &&38 typeof v.audience === "string" &&39 Array.isArray(v.pages) &&40 typeof v.tone === "string" &&41 Array.isArray(v.constraints)42 )43}4445export function parseProjectBrief(raw: string): ProjectBrief | null {46 try {47 const data = JSON.parse(raw) as unknown48 return isProjectBrief(data) ? data : null49 } catch {50 return null51 }52}5354export function briefOgTitle(brief: ProjectBrief): string {55 return (brief.ogTitle ?? brief.name).trim()56}5758export function briefOgSubtitle(brief: ProjectBrief): string {59 return (brief.ogSubtitle ?? brief.oneLiner).trim()60}6162export function briefThumbnailTitle(brief: ProjectBrief): string {63 return (brief.thumbnailTitle ?? brief.ogTitle ?? brief.name).trim()64}6566export function buildOgHref(67 brief: ProjectBrief,68 options?: { path?: string; style?: string }69): string {70 const path = options?.path ?? "/og"71 const title = briefOgTitle(brief)72 const subtitle = briefOgSubtitle(brief)73 const params = new URLSearchParams({ mode: "quick" })74 if (title) params.set("title", title)75 if (subtitle) params.set("subtitle", subtitle)76 if (options?.style) params.set("style", options.style)77 const qs = params.toString()78 return `${path}?${qs}#og-workspace`79}8081export function buildThumbnailHref(82 brief: ProjectBrief,83 options?: { path?: string }84): string {85 const path = options?.path ?? "/thumbnail"86 const title = briefThumbnailTitle(brief)87 const params = new URLSearchParams()88 if (title) params.set("title", title)89 const qs = params.toString()90// … truncated
Files it writes
More from atroui
All 82 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| Analyticsanalytics | atroui | Utilities | Free | no deps | |
| Brandbrand | atroui | Utilities | Free | no deps | |
| SEO helpersseo | atroui | Utilities | Free | no deps | |
| Site URLsite-url | atroui | Utilities | Free | no deps | |
| Utilsutils | atroui | Utilities | Free | 2 deps |
