@@ -681,7 +762,7 @@ function LaunchBriefPanel({
}
function getLaunchBriefSectionCount(brief: RepoLaunchBriefSummary) {
- return 6 + (brief.audienceDiscovery ? 1 : 0) + (brief.storyMap ? 1 : 0);
+ return 6 + (brief.audienceDiscovery ? 1 : 0) + (brief.storyMap ? 1 : 0) + (brief.launchMaterialsMap ? 1 : 0);
}
function getArtifactDownloadHref(artifact: RepoLaunchBriefArtifactSummary) {
@@ -708,6 +789,7 @@ function serializeLaunchBrief(brief: RepoLaunchBriefSummary, repoFullName: strin
"",
...(brief.audienceDiscovery ? [serializeAudienceDiscovery(brief.audienceDiscovery), ""] : []),
...(brief.storyMap ? [serializeStoryMap(brief.storyMap), ""] : []),
+ ...(brief.launchMaterialsMap ? [serializeLaunchMaterialsMap(brief.launchMaterialsMap), ""] : []),
"README checklist:",
...brief.readmeChecklist.map((item) => `- ${item.item} (${item.source})`),
"",
@@ -761,10 +843,36 @@ function serializeStoryMap(storyMap: RepoLaunchStoryMapSummary) {
].join("\n");
}
+function serializeLaunchMaterialsMap(launchMaterialsMap: RepoLaunchMaterialsMapSummary) {
+ return [
+ `Launch materials map: ${launchMaterialsMap.title}`,
+ "",
+ launchMaterialsMap.summary,
+ "",
+ ...launchMaterialsMap.channels.map((channel, index) =>
+ [
+ `${index + 1}. ${channel.label}`,
+ ` Channel: ${channel.type}`,
+ ` Primary user: ${channel.primaryUser}`,
+ ` Job to be done: ${channel.jobToBeDone}`,
+ ` Artifact: ${channel.artifactLabel}`,
+ ` Channel fit: ${channel.channelFit}`,
+ ` Review question: ${channel.reviewQuestion}`,
+ ` Success signal: ${channel.successSignal}`,
+ ` Source: ${channel.source}`,
+ ].join("\n"),
+ ),
+ ].join("\n");
+}
+
function getAudienceChannelCount(audienceDiscovery: RepoLaunchAudienceDiscoverySummary) {
return new Set(audienceDiscovery.signals.map((signal) => signal.whereToFind)).size;
}
+function getLaunchMaterialArtifactTypeCount(launchMaterialsMap: RepoLaunchMaterialsMapSummary) {
+ return new Set(launchMaterialsMap.channels.map((channel) => channel.type)).size;
+}
+
function ProductAnimationPanel() {
const videoRef = useRef(null);
diff --git a/src/lib/analytics.ts b/src/lib/analytics.ts
index 2a5afb6..a475092 100644
--- a/src/lib/analytics.ts
+++ b/src/lib/analytics.ts
@@ -17,6 +17,7 @@ export type AnalyticsEventName =
| "launch_brief_copied"
| "launch_audience_map_copied"
| "launch_story_map_copied"
+ | "launch_materials_map_copied"
| "launch_artifact_copied"
| "launch_artifact_downloaded"
| "generated_image_preview_opened"
diff --git a/src/marketing/link-catalog.ts b/src/marketing/link-catalog.ts
index 5043154..f92f25a 100644
--- a/src/marketing/link-catalog.ts
+++ b/src/marketing/link-catalog.ts
@@ -120,6 +120,25 @@ export const marketingLinks: readonly MarketingLink[] = [
content: "product_page",
},
},
+ {
+ status: "published",
+ funnelStage: "top",
+ buyerStage: "consideration",
+ persona: "ai_project_builder",
+ intentCluster: "github_repo_launch_materials_map",
+ pageType: "product",
+ slug: "github-repo-launch-materials-map",
+ canonicalUrl: "https://seekersai.com/product/github-repo-launch-materials-map",
+ primaryKeyword: "github repo launch materials map",
+ primaryCta: "generate_launch_card",
+ crmCampaign: "2026_q2_launch_materials_map",
+ utm: {
+ source: "google",
+ medium: "organic",
+ campaign: "launch_materials_map",
+ content: "product_page",
+ },
+ },
{
status: "published",
funnelStage: "top",
diff --git a/src/marketing/page-content.ts b/src/marketing/page-content.ts
index 7cf4527..3a3b8e1 100644
--- a/src/marketing/page-content.ts
+++ b/src/marketing/page-content.ts
@@ -330,6 +330,97 @@ const pageNarratives: Partial> = {
],
lastUpdated: "June 2, 2026",
},
+ github_repo_launch_materials_map: {
+ definition:
+ "A GitHub repo launch materials map is a source-backed channel plan that maps one repository URL into README, social, deck, visual, and outreach assets. Each channel names the target user, artifact, source evidence, review question, and success signal so builders can review launch materials before publishing.",
+ targetUser:
+ "AI project builders, open-source maintainers, technical founders, DevRel operators, and product marketers preparing a cold-start repository launch.",
+ jobToBeDone:
+ "When a generated repo brief produces multiple launch artifacts, help the builder decide which material belongs on which channel, who it is for, what source evidence supports it, and what activation signal to watch next.",
+ evidenceBoundary:
+ "The map should use repository metadata, README evidence, linked docs, official identity assets, generated quality reports, or explicit user input. It should not promise search placement, financial outcomes, adoption, Product Hunt outcomes, exact pricing, or automated publishing.",
+ benefits: [
+ {
+ title: "Map every material to a job",
+ body: "Tie README, social, deck, visual, and outreach outputs to a target user, job-to-be-done, artifact, source evidence, review question, and success signal.",
+ },
+ {
+ title: "Keep cold-start launch work reviewable",
+ body: "Show which source-backed claim belongs in each channel before the builder copies, downloads, or requests a full package.",
+ },
+ {
+ title: "Measure activation by artifact behavior",
+ body: "Track copy and download behavior by artifact type so QuickFork can learn which materials create value before adding pricing or scale.",
+ },
+ {
+ title: "Make the product workflow AI-readable",
+ body: "Expose the materials map as a crawlable product page with definition, FAQ, source notes, and CTA back to the generator.",
+ },
+ ],
+ workflow: [
+ {
+ title: "Start from one repository URL",
+ body: "QuickFork reads README, metadata, topics, source references, identity assets, and explicit user notes.",
+ },
+ {
+ title: "Build the free repo launch brief",
+ body: "The generation flow creates target-user discovery, a story map, source references, and channel artifacts.",
+ },
+ {
+ title: "Map artifacts to channels",
+ body: "The materials map assigns README, social, deck, visual, and outreach outputs to users, jobs, review questions, and success signals.",
+ },
+ {
+ title: "Copy, download, and validate",
+ body: "Builders export the useful artifacts, then compare page source, generation, copy, download, and full-package request behavior.",
+ },
+ ],
+ faqs: [
+ {
+ question: "What is a GitHub repo launch materials map?",
+ answer:
+ "It is a source-backed channel plan that maps one repository URL into README, social, deck, visual, and outreach assets, with target user, artifact, source evidence, review question, and success signal for each channel.",
+ },
+ {
+ question: "How does the materials map help cold-start launches?",
+ answer:
+ "It keeps every launch material tied to a specific user job and source boundary before the project has mature public proof, so builders can review and ship the most useful channels first.",
+ },
+ {
+ question: "What does QuickFork measure after generating the map?",
+ answer:
+ "QuickFork can measure launch brief views, materials-map copies, artifact copies and downloads, generation completions, and full launch package requests without sending raw README text or artifact bodies to browser analytics.",
+ },
+ {
+ question: "Does the materials map publish assets automatically?",
+ answer:
+ "No. It is a review and planning surface. Humans still approve claims, visuals, examples, pricing language, and public publishing choices.",
+ },
+ ],
+ sourceNotes: [
+ {
+ label: "GitHub Docs About READMEs",
+ body: "GitHub treats the README as the primary repository explanation surface, so a channel map should start with README evidence.",
+ url: "https://docs.github.com/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-readmes",
+ },
+ {
+ label: "GitHub Docs social preview",
+ body: "GitHub social preview customization makes shared-link visuals a concrete material in repository launch planning.",
+ url: "https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/customizing-your-repositorys-social-media-preview?apiVersion=2022-11-28",
+ },
+ {
+ label: "Open Source Guides finding users",
+ body: "Open Source Guides connects audience discovery and feedback loops to open-source launch work.",
+ url: "https://opensource.guide/finding-users/",
+ },
+ {
+ label: "Product Hunt launch guide",
+ body: "Product Hunt launch preparation makes story, media, maker context, and launch-day copy practical review surfaces.",
+ url: "https://www.producthunt.com/launch/preparing-for-launch",
+ },
+ ],
+ lastUpdated: "June 3, 2026",
+ },
readme_marketing_cards: {
definition:
"README marketing cards are README-first hero cards, GitHub social preview direction, and launch visuals grounded in repository evidence and human review. They help visitors understand what a technical project does before reading the full README, code, benchmark notes, or launch announcement.",
@@ -1195,6 +1286,9 @@ export function getMarketingPageHeadline(link: MarketingLink) {
if (link.intentCluster === "cold_start_launch_materials") {
return "Cold Start Launch Materials From A GitHub Repo.";
}
+ if (link.intentCluster === "github_repo_launch_materials_map") {
+ return "GitHub Repo Launch Materials Map for source-backed channel planning.";
+ }
if (link.intentCluster === "readme_marketing_cards") {
return "README Marketing Cards for source-backed repository visuals.";
}
@@ -1258,6 +1352,9 @@ export function getMarketingPageDescription(link: MarketingLink) {
if (link.intentCluster === "cold_start_launch_materials") {
return "QuickFork maps cold start launch materials demand into source-backed README, social, deck, visual, and outreach drafts generated from one public GitHub repository URL.";
}
+ if (link.intentCluster === "github_repo_launch_materials_map") {
+ return "QuickFork maps github repo launch materials map demand into a source-backed channel plan for README, social, deck, visual, and outreach assets from one repository URL.";
+ }
if (link.intentCluster === "readme_marketing_cards") {
return "QuickFork maps readme marketing cards demand into README-first hero cards, GitHub social preview direction, and launch visuals grounded in repository evidence and human review.";
}
diff --git a/src/seo/public-growth.test.ts b/src/seo/public-growth.test.ts
index 1e420cf..78447fe 100644
--- a/src/seo/public-growth.test.ts
+++ b/src/seo/public-growth.test.ts
@@ -33,6 +33,7 @@ describe("public growth infrastructure", () => {
expect(sitemap).toContain(`${link.canonicalUrl}`);
}
expect(sitemap).toContain("https://seekersai.com/product/cold-start-launch-materials");
+ expect(sitemap).toContain("https://seekersai.com/product/github-repo-launch-materials-map");
expect(sitemap).toContain("https://seekersai.com/product/github-repo-visual-explainer");
expect(sitemap).toContain("https://seekersai.com/product/github-repo-to-launch-deck");
expect(sitemap).toContain("https://seekersai.com/product/github-repo-to-product-outreach");
@@ -61,6 +62,11 @@ describe("public growth infrastructure", () => {
expect(llms).toContain(
"source-backed README, social, deck, visual, and outreach drafts generated from one public GitHub repository URL",
);
+ expect(llms).toContain("https://seekersai.com/product/github-repo-launch-materials-map");
+ expect(llms).toContain("GitHub Repo Launch Materials Map");
+ expect(llms).toContain(
+ "source-backed channel plan for README, social, deck, visual, and outreach assets from one repository URL",
+ );
expect(llms).toContain("https://seekersai.com/product/readme-marketing-cards");
expect(llms).toContain("README Marketing Cards");
expect(llms).toContain(
diff --git a/src/seo/semantic-links.test.ts b/src/seo/semantic-links.test.ts
index 8d492f9..d75f7cb 100644
--- a/src/seo/semantic-links.test.ts
+++ b/src/seo/semantic-links.test.ts
@@ -225,6 +225,12 @@ describe("typed semantic marketing link catalog", () => {
primaryCta: "generate_launch_card",
}),
);
+ expect(getMarketingLinkByPath("/product/github-repo-launch-materials-map")).toEqual(
+ expect.objectContaining({
+ intentCluster: "github_repo_launch_materials_map",
+ primaryKeyword: "github repo launch materials map",
+ }),
+ );
expect(getMarketingLinkByPath("/product/readme-marketing-cards")).toEqual(
expect.objectContaining({
intentCluster: "readme_marketing_cards",
@@ -268,6 +274,16 @@ describe("typed semantic marketing link catalog", () => {
expect(getMarketingPageDescription(link!)).not.toMatch(/guaranteed|rankings|revenue|customers|viral/i);
});
+ it("publishes a GitHub repo launch materials map product page contract", () => {
+ const link = getMarketingLinkByPath("/product/github-repo-launch-materials-map");
+
+ expect(link).toBeDefined();
+ expect(getMarketingPageTitle(link!)).toContain("GitHub Repo Launch Materials Map");
+ expect(getMarketingPageHeadline(link!)).toContain("GitHub Repo Launch Materials Map");
+ expect(getMarketingPageDescription(link!)).toContain("source-backed channel plan");
+ expect(getMarketingPageDescription(link!)).not.toMatch(/guaranteed|rankings|revenue|customers|viral/i);
+ });
+
it("publishes a README marketing cards product page contract", () => {
const link = getMarketingLinkByPath("/product/readme-marketing-cards");
diff --git a/src/server/generation/generation.test.ts b/src/server/generation/generation.test.ts
index 8479e56..29bd247 100644
--- a/src/server/generation/generation.test.ts
+++ b/src/server/generation/generation.test.ts
@@ -542,9 +542,36 @@ describe("project launch generation backend", () => {
}),
);
expect(result.launchBrief.storyMap.nodes[2]?.detail).toContain("->");
+ expect(result.launchBrief.launchMaterialsMap.title).toContain("nexu-io/open-design");
+ expect(result.launchBrief.launchMaterialsMap.channels.map((channel) => channel.type)).toEqual([
+ "readme",
+ "social",
+ "deck",
+ "visual",
+ "outreach",
+ ]);
+ expect(result.launchBrief.launchMaterialsMap.channels[0]).toEqual(
+ expect.objectContaining({
+ type: "readme",
+ label: "README launch section",
+ primaryUser: expect.stringContaining("Open-source"),
+ jobToBeDone: expect.stringContaining("understand"),
+ reviewQuestion: expect.stringContaining("source"),
+ successSignal: expect.stringContaining("README"),
+ source: expect.stringContaining("README or repo metadata includes"),
+ }),
+ );
+ expect(result.launchBrief.launchMaterialsMap.channels[3]).toEqual(
+ expect.objectContaining({
+ type: "visual",
+ artifactLabel: "Visual explainer prompt",
+ reviewQuestion: expect.stringContaining("identity"),
+ }),
+ );
expect(result.launchBrief.artifacts.map((artifact) => artifact.type)).toEqual([
"audience",
"story_map",
+ "materials_map",
"readme",
"social",
"deck",
@@ -567,6 +594,13 @@ describe("project launch generation backend", () => {
body: expect.stringContaining("## Project story map"),
sourceReferences: expect.arrayContaining([expect.stringContaining("README or repo metadata includes")]),
}),
+ expect.objectContaining({
+ type: "materials_map",
+ label: "Launch materials map",
+ fileName: "nexu-io-open-design-launch-materials-map.md",
+ body: expect.stringContaining("## Launch materials map"),
+ sourceReferences: expect.arrayContaining([expect.stringContaining("README or repo metadata includes")]),
+ }),
expect.objectContaining({
type: "readme",
label: "README launch brief",
diff --git a/src/server/generation/launch-brief.ts b/src/server/generation/launch-brief.ts
index d098420..220b9e7 100644
--- a/src/server/generation/launch-brief.ts
+++ b/src/server/generation/launch-brief.ts
@@ -8,6 +8,7 @@ import type {
RepoLaunchBriefAngle,
RepoLaunchBriefArtifact,
RepoLaunchBriefChecklistItem,
+ RepoLaunchMaterialsMap,
RepoLaunchStoryMap,
VisualDirection,
} from "./types.js";
@@ -65,12 +66,26 @@ export function buildRepoLaunchBrief(input: {
sourceReferences,
visualCategory: input.visualDirection.category,
});
+ const launchMaterialsMap = buildLaunchMaterialsMap({
+ repoFullName: input.metadata.fullName,
+ summary: input.brief.subtitle,
+ audience,
+ audienceDiscovery,
+ storyMap,
+ readmeChecklist,
+ launchAngles,
+ socialPost,
+ deckOutline,
+ sourceReferences,
+ visualCategory: input.visualDirection.category,
+ });
return {
summary: input.brief.subtitle,
audienceHypothesis: audience,
audienceDiscovery,
storyMap,
+ launchMaterialsMap,
readmeChecklist,
launchAngles,
socialPost,
@@ -84,6 +99,7 @@ export function buildRepoLaunchBrief(input: {
audienceHypothesis: audience,
audienceDiscovery,
storyMap,
+ launchMaterialsMap,
readmeChecklist,
launchAngles,
socialPost,
@@ -101,6 +117,7 @@ function buildLaunchBriefArtifacts(input: {
audienceHypothesis: string;
audienceDiscovery: RepoLaunchAudienceDiscovery;
storyMap: RepoLaunchStoryMap;
+ launchMaterialsMap: RepoLaunchMaterialsMap;
readmeChecklist: RepoLaunchBriefChecklistItem[];
launchAngles: RepoLaunchBriefAngle[];
socialPost: string;
@@ -127,6 +144,13 @@ function buildLaunchBriefArtifacts(input: {
body: formatStoryMap(input.storyMap, sourceBlock),
sourceReferences: input.sourceReferences,
},
+ {
+ type: "materials_map",
+ label: "Launch materials map",
+ fileName: `${slug}-launch-materials-map.md`,
+ body: formatLaunchMaterialsMap(input.launchMaterialsMap, sourceBlock),
+ sourceReferences: input.sourceReferences,
+ },
{
type: "readme",
label: "README launch brief",
@@ -236,6 +260,91 @@ function buildAudienceDiscovery(input: {
};
}
+function buildLaunchMaterialsMap(input: {
+ repoFullName: string;
+ summary: string;
+ audience: string;
+ audienceDiscovery: RepoLaunchAudienceDiscovery;
+ storyMap: RepoLaunchStoryMap;
+ readmeChecklist: RepoLaunchBriefChecklistItem[];
+ launchAngles: RepoLaunchBriefAngle[];
+ socialPost: string;
+ deckOutline: string[];
+ sourceReferences: string[];
+ visualCategory: VisualDirection["category"];
+}): RepoLaunchMaterialsMap {
+ const primarySource = input.sourceReferences[0] ?? "Repository evidence is limited; review generated claims before publishing.";
+ const secondarySource = input.sourceReferences[1] ?? primarySource;
+ const adopterSignal = input.audienceDiscovery.signals.find((signal) => signal.id === "open_source_adopters");
+ const reviewerSignal = input.audienceDiscovery.signals.find((signal) => signal.id === "launch_reviewers");
+ const technicalSignal = input.audienceDiscovery.signals.find((signal) => signal.id === "technical_builders");
+ const topAngle = input.launchAngles[0]?.body ?? input.summary;
+ const firstChecklistItem = input.readmeChecklist[0]?.item ?? "Lead with a source-backed README value proposition.";
+ const workflowNode = input.storyMap.nodes.find((node) => node.id === "workflow");
+
+ return {
+ title: `${input.repoFullName} launch materials map`,
+ summary: `Channel plan for README, social, deck, visual, and outreach launch materials from ${input.summary}`,
+ channels: [
+ {
+ type: "readme",
+ label: "README launch section",
+ primaryUser: adopterSignal?.segment ?? "Open-source adopters and README visitors",
+ jobToBeDone: `Help visitors understand ${input.repoFullName} before reading implementation details.`,
+ artifactLabel: "README launch brief",
+ channelFit: `Use the README section to surface "${firstChecklistItem}" before lower-level repository detail.`,
+ source: primarySource,
+ reviewQuestion: "Which source-backed claim belongs in the README hero without overstating proof?",
+ successSignal: "README artifact copied or downloaded; visitor continues into generation or full package request.",
+ },
+ {
+ type: "social",
+ label: "Social launch post",
+ primaryUser: reviewerSignal?.segment ?? "Launch reviewers and technical social followers",
+ jobToBeDone: "Decide whether the project is worth clicking before opening GitHub.",
+ artifactLabel: "Social launch post",
+ channelFit: `Lead with "${input.socialPost.split("\n")[0]}" and keep the repo URL visible.`,
+ source: secondarySource,
+ reviewQuestion: "Does the post explain the project without invented traction, adoption, or pricing?",
+ successSignal: "Social artifact copied or downloaded; campaign UTM drives generation_started.",
+ },
+ {
+ type: "deck",
+ label: "Launch deck outline",
+ primaryUser: "Technical founders, demo reviewers, and DevRel operators",
+ jobToBeDone: "Turn the repository story into a short launch narrative for demos, internal review, or Product Hunt prep.",
+ artifactLabel: "Pitch deck outline",
+ channelFit: `Anchor the deck around ${input.deckOutline.length} source-backed slides and the workflow ${workflowNode?.detail ?? "from repo evidence"}.`,
+ source: secondarySource,
+ reviewQuestion: "Which deck slide needs the strongest source citation before sharing outside the team?",
+ successSignal: "Deck artifact copied or downloaded; full launch package CTA clicked after artifact review.",
+ },
+ {
+ type: "visual",
+ label: "Visual project explainer",
+ primaryUser: technicalSignal?.segment ?? input.audience,
+ jobToBeDone: "Understand the project workflow and proof boundary without parsing the full README.",
+ artifactLabel: "Visual explainer prompt",
+ channelFit: `Use the ${input.visualCategory} direction to keep README, social preview, and deck visuals aligned.`,
+ source: primarySource,
+ reviewQuestion: "Does the visual direction preserve identity assets and avoid fake logos or unsupported diagrams?",
+ successSignal: "Visual prompt copied, generated image preview opened, or image downloaded.",
+ },
+ {
+ type: "outreach",
+ label: "Product outreach draft",
+ primaryUser: "DevRel operators, partner editors, and launch communities",
+ jobToBeDone: "Ask for feedback or distribution using a human-reviewed source-backed note.",
+ artifactLabel: "Product outreach draft",
+ channelFit: `Use a short outreach note centered on "${topAngle}" and keep it reviewable before sending.`,
+ source: primarySource,
+ reviewQuestion: "Which recipient segment should review this outreach draft before public distribution?",
+ successSignal: "Outreach artifact copied or downloaded; qualified contact request references launch review.",
+ },
+ ],
+ };
+}
+
function buildStoryMap(input: {
repoFullName: string;
summary: string;
@@ -330,6 +439,32 @@ function formatStoryMap(storyMap: RepoLaunchStoryMap, sourceBlock: string) {
].join("\n");
}
+function formatLaunchMaterialsMap(launchMaterialsMap: RepoLaunchMaterialsMap, sourceBlock: string) {
+ return [
+ `# ${launchMaterialsMap.title}`,
+ "",
+ "## Launch materials map",
+ "",
+ launchMaterialsMap.summary,
+ "",
+ ...launchMaterialsMap.channels.map((channel, index) =>
+ [
+ `${index + 1}. ${channel.label}`,
+ ` Channel: ${channel.type}`,
+ ` Primary user: ${channel.primaryUser}`,
+ ` Job to be done: ${channel.jobToBeDone}`,
+ ` Artifact: ${channel.artifactLabel}`,
+ ` Channel fit: ${channel.channelFit}`,
+ ` Review question: ${channel.reviewQuestion}`,
+ ` Success signal: ${channel.successSignal}`,
+ ` Source: ${channel.source}`,
+ ].join("\n"),
+ ),
+ "",
+ sourceBlock,
+ ].join("\n");
+}
+
function formatSourceReferences(sourceReferences: string[]) {
return ["## Source references", ...sourceReferences.map((source) => `- ${source}`)].join("\n");
}
diff --git a/src/server/generation/types.ts b/src/server/generation/types.ts
index 5bb5847..1c6eefb 100644
--- a/src/server/generation/types.ts
+++ b/src/server/generation/types.ts
@@ -228,7 +228,27 @@ export interface RepoLaunchStoryMap {
nodes: RepoLaunchStoryMapNode[];
}
-export type RepoLaunchBriefArtifactType = "audience" | "story_map" | "readme" | "social" | "deck" | "outreach" | "visual";
+export type RepoLaunchMaterialChannelType = "readme" | "social" | "deck" | "visual" | "outreach";
+
+export interface RepoLaunchMaterialChannel {
+ type: RepoLaunchMaterialChannelType;
+ label: string;
+ primaryUser: string;
+ jobToBeDone: string;
+ artifactLabel: string;
+ channelFit: string;
+ source: string;
+ reviewQuestion: string;
+ successSignal: string;
+}
+
+export interface RepoLaunchMaterialsMap {
+ title: string;
+ summary: string;
+ channels: RepoLaunchMaterialChannel[];
+}
+
+export type RepoLaunchBriefArtifactType = "audience" | "story_map" | "materials_map" | "readme" | "social" | "deck" | "outreach" | "visual";
export interface RepoLaunchBriefArtifact {
type: RepoLaunchBriefArtifactType;
@@ -243,6 +263,7 @@ export interface RepoLaunchBrief {
audienceHypothesis: string;
audienceDiscovery: RepoLaunchAudienceDiscovery;
storyMap: RepoLaunchStoryMap;
+ launchMaterialsMap: RepoLaunchMaterialsMap;
readmeChecklist: RepoLaunchBriefChecklistItem[];
launchAngles: RepoLaunchBriefAngle[];
socialPost: string;
diff --git a/src/styles/app.css b/src/styles/app.css
index 148935a..9edfa3c 100644
--- a/src/styles/app.css
+++ b/src/styles/app.css
@@ -1127,6 +1127,98 @@ blockquote {
line-height: 1.4;
}
+.launchMaterialsMap {
+ border: 1px solid var(--border);
+ display: grid;
+ background: #f7fbf8;
+}
+
+.launchMaterialsMapHead {
+ padding: 14px;
+ display: grid;
+ grid-template-columns: minmax(0, 1fr) auto;
+ gap: 12px;
+ align-items: center;
+ border-bottom: 1px solid var(--border);
+}
+
+.launchMaterialsMapHead strong {
+ display: block;
+ font-size: 15px;
+ line-height: 1.25;
+}
+
+.launchMaterialsMapHead small {
+ display: block;
+ margin-top: 4px;
+ color: var(--muted);
+ font-size: 13px;
+ line-height: 1.4;
+}
+
+.launchMaterialsMapChannels {
+ margin: 0;
+ padding: 0;
+ display: grid;
+ list-style: none;
+}
+
+.launchMaterialsMapChannels li {
+ padding: 14px;
+ border-bottom: 1px solid var(--border);
+ display: grid;
+ gap: 8px;
+}
+
+.launchMaterialsMapChannels li:last-child {
+ border-bottom: 0;
+}
+
+.launchMaterialsMapChannels span {
+ width: fit-content;
+ padding: 3px 7px;
+ border: 1px solid var(--border);
+ background: #ffffff;
+ color: var(--muted);
+ font: 700 11px/1.2 var(--font-mono);
+ text-transform: uppercase;
+}
+
+.launchMaterialsMapChannels strong {
+ font-size: 15px;
+ line-height: 1.25;
+}
+
+.launchMaterialsMapChannels dl {
+ margin: 0;
+ display: grid;
+ grid-template-columns: repeat(2, minmax(0, 1fr));
+ gap: 8px 12px;
+}
+
+.launchMaterialsMapChannels div {
+ min-width: 0;
+}
+
+.launchMaterialsMapChannels dt {
+ color: var(--muted);
+ font: 700 10px/1.2 var(--font-mono);
+ text-transform: uppercase;
+}
+
+.launchMaterialsMapChannels dd {
+ margin: 3px 0 0;
+ color: var(--fg);
+ font-size: 13px;
+ line-height: 1.45;
+}
+
+.launchMaterialsMapChannels small {
+ color: var(--muted);
+ font-size: 12px;
+ line-height: 1.4;
+}
+
.launchArtifactList {
border: 1px solid var(--border);
display: grid;
@@ -3289,6 +3381,8 @@ blockquote {
.launchAudienceDiscoveryHead,
.launchAudienceDiscoverySignals dl,
.launchStoryMapHead,
+ .launchMaterialsMapHead,
+ .launchMaterialsMapChannels dl,
.launchArtifactIntro,
.launchArtifactRow,
.launchPackageCta,