rspace-online/server/seed-campaign.ts

496 lines
15 KiB
TypeScript

/**
* Social Media Campaign seed — "MycoFi Earth Launch" campaign
*
* Demonstrates the folk-social-post component with a realistic
* multi-platform product launch campaign connected by folk-arrows
* in an n8n-style "this then that" flow.
*
* Flow layout (left-to-right, with parallel branches):
*
* [Trigger] → [X Teaser] → [LinkedIn Thought] → [IG Carousel] ──┐
* ├→ [YT Video] → [X Launch] → [LinkedIn Ann.] ──┐
* │ ├→ [IG Reel] → [Threads] → [Bluesky]
* └───────────────────────────────────────────────┘
*/
import {
addShapes,
communityExists,
createCommunity,
getDocumentData,
loadCommunity,
} from "./community-store";
// ── Layout constants ────────────────────────────────────────────
const COL_WIDTH = 320;
const COL_GAP = 100;
const ROW_HEIGHT = 420;
const ROW_GAP = 60;
const START_X = 60;
const START_Y = 60;
const NODE_W = 300;
const NODE_H = 380;
function col(n: number): number {
return START_X + n * (COL_WIDTH + COL_GAP);
}
function row(n: number): number {
return START_Y + n * (ROW_HEIGHT + ROW_GAP);
}
// ── Campaign seed data ──────────────────────────────────────────
const CAMPAIGN_SHAPES: Record<string, unknown>[] = [
// ────────────────────────────────────────────────────────────
// TRIGGER NODE (campaign start)
// ────────────────────────────────────────────────────────────
{
id: "campaign-trigger",
type: "folk-workflow-block",
x: col(0),
y: row(0) + 100,
width: 220,
height: 140,
rotation: 0,
blockType: "trigger",
label: "Campaign Start",
inputs: [],
outputs: [{ name: "launch", type: "trigger" }],
},
// ────────────────────────────────────────────────────────────
// PHASE 1: Pre-Launch Hype (Days -3 to -1)
// ────────────────────────────────────────────────────────────
{
id: "post-x-teaser",
type: "folk-social-post",
x: col(1),
y: row(0),
width: NODE_W,
height: NODE_H,
rotation: 0,
platform: "x",
postType: "thread",
stepNumber: 1,
content:
"Something is growing in the mycelium... \ud83c\udf44\n\nFor the past 2 years, we've been building the infrastructure for a regenerative economy.\n\nOn Feb 24, we reveal everything.\n\nA thread on why the old financial system is composting itself \ud83e\uddf5\ud83d\udc47",
mediaUrl: "",
mediaType: "",
scheduledAt: "2026-02-21T09:00:00",
status: "scheduled",
hashtags: ["MycoFi", "RegenFinance", "Web3", "ComingSoon"],
},
{
id: "post-linkedin-thought",
type: "folk-social-post",
x: col(2),
y: row(0),
width: NODE_W,
height: NODE_H,
rotation: 0,
platform: "linkedin",
postType: "article",
stepNumber: 2,
content:
"The regenerative finance movement isn't just about returns \u2014 it's about redesigning incentive structures from the ground up.\n\nIn this article, I break down why mycelial network theory offers the best model for decentralized economic coordination.\n\n3 key insights from 2 years of building MycoFi Earth...",
mediaUrl: "",
mediaType: "image",
scheduledAt: "2026-02-22T11:00:00",
status: "scheduled",
hashtags: ["RegenerativeFinance", "DeFi", "SystemsThinking", "Leadership"],
},
{
id: "post-ig-carousel",
type: "folk-social-post",
x: col(3),
y: row(0),
width: NODE_W,
height: NODE_H,
rotation: 0,
platform: "instagram",
postType: "carousel",
stepNumber: 3,
content:
"5 Ways Mycelium Networks Mirror the Future of Finance \ud83c\udf0d\ud83c\udf44\n\nSlide 1: The problem with extractive finance\nSlide 2: How mycelium redistributes nutrients\nSlide 3: Token-weighted funding circles\nSlide 4: Community governance that actually works\nSlide 5: Join the launch \u2014 Feb 24",
mediaUrl: "",
mediaType: "carousel",
scheduledAt: "2026-02-23T14:00:00",
status: "scheduled",
hashtags: [
"MycoFi",
"RegenerativeEconomy",
"Infographic",
"Web3Education",
],
},
// ────────────────────────────────────────────────────────────
// PHASE 2: Launch Day (Day 0)
// ────────────────────────────────────────────────────────────
{
id: "post-yt-launch",
type: "folk-social-post",
x: col(4),
y: row(0) - 30,
width: NODE_W,
height: NODE_H,
rotation: 0,
platform: "youtube",
postType: "video",
stepNumber: 4,
content:
"MycoFi Earth \u2014 Official Launch Video\n\nThe regenerative economy starts here. Watch how mycelial intelligence is reshaping finance, governance, and community coordination.\n\nFeaturing interviews with 12 builders from the ecosystem.\n\n[18:42]",
mediaUrl: "",
mediaType: "video",
scheduledAt: "2026-02-24T10:00:00",
status: "draft",
hashtags: [
"MycoFiLaunch",
"RegenerativeFinance",
"Documentary",
"Web3",
],
},
{
id: "post-x-launch",
type: "folk-social-post",
x: col(5),
y: row(0) - 60,
width: NODE_W,
height: NODE_H,
rotation: 0,
platform: "x",
postType: "thread",
stepNumber: 5,
content:
"\ud83c\udf44 MycoFi Earth is LIVE \ud83c\udf44\n\nAfter 2 years of building, the regenerative finance platform is here.\n\nWhat is it?\n\u2022 Token-weighted funding circles\n\u2022 Mycelial governance (no whales)\n\u2022 Composting mechanism for failed proposals\n\u2022 100% on-chain, 100% community-owned\n\n\ud83d\udc47 Full breakdown thread",
mediaUrl: "",
mediaType: "image",
scheduledAt: "2026-02-24T10:15:00",
status: "draft",
hashtags: [
"MycoFi",
"Launch",
"RegenFinance",
"DeFi",
"DAO",
],
},
{
id: "post-linkedin-launch",
type: "folk-social-post",
x: col(6),
y: row(0) - 30,
width: NODE_W,
height: NODE_H,
rotation: 0,
platform: "linkedin",
postType: "text",
stepNumber: 6,
content:
"Today we're launching MycoFi Earth \u2014 a regenerative finance platform modeled on mycelial networks.\n\nWhy it matters for the future of organizational design:\n\n1. Composting mechanism: Failed proposals return resources to the network\n2. Nutrient routing: Funds flow to where they're needed most\n3. No single point of failure: True decentralization\n\nFull video + docs in comments \u2193",
mediaUrl: "",
mediaType: "image",
scheduledAt: "2026-02-24T11:00:00",
status: "draft",
hashtags: [
"Launch",
"RegenerativeFinance",
"Innovation",
"FutureOfWork",
],
},
// ────────────────────────────────────────────────────────────
// PHASE 3: Post-Launch Amplification (Day +1)
// ────────────────────────────────────────────────────────────
{
id: "post-ig-reel",
type: "folk-social-post",
x: col(7),
y: row(0) - 30,
width: NODE_W,
height: NODE_H,
rotation: 0,
platform: "instagram",
postType: "reel",
stepNumber: 7,
content:
"60-second explainer: How MycoFi Earth works \ud83c\udf44\u2728\n\nVisual breakdown of the token flow from contributor \u2192 funding circle \u2192 project \u2192 compost.\n\nSet to lo-fi beats with mycelium time-lapse footage.\n\nCTA: Link in bio to join the first funding circle.",
mediaUrl: "",
mediaType: "video",
scheduledAt: "2026-02-25T12:00:00",
status: "draft",
hashtags: [
"MycoFi",
"RegenFinance",
"Explainer",
"Web3",
"Reels",
],
},
{
id: "post-threads-xpost",
type: "folk-social-post",
x: col(8),
y: row(0) - 60,
width: NODE_W,
height: NODE_H,
rotation: 0,
platform: "threads",
postType: "text",
stepNumber: 8,
content:
"We just launched MycoFi Earth and the response has been incredible \ud83c\udf1f\n\nThe idea is simple: what if finance worked like mycelium?\n\nMycelium doesn't hoard \u2014 it redistributes. MycoFi applies that logic to community funding.\n\nEarly access is open. Come grow with us \ud83c\udf31",
mediaUrl: "",
mediaType: "",
scheduledAt: "2026-02-25T14:00:00",
status: "draft",
hashtags: ["MycoFi", "RegenEconomy", "Community"],
},
{
id: "post-bluesky-launch",
type: "folk-social-post",
x: col(9),
y: row(0),
width: NODE_W,
height: NODE_H,
rotation: 0,
platform: "bluesky",
postType: "text",
stepNumber: 9,
content:
"MycoFi Earth just went live \ud83c\udf44\n\nIt's a regenerative finance platform where funding flows like nutrients through a mycelial network.\n\nNo VCs. No whales. Just communities funding what matters.\n\nmycofi.earth",
mediaUrl: "",
mediaType: "",
scheduledAt: "2026-02-25T15:00:00",
status: "draft",
hashtags: ["MycoFi", "RegenFinance", "Bluesky"],
},
// ────────────────────────────────────────────────────────────
// CAMPAIGN SUMMARY NODE
// ────────────────────────────────────────────────────────────
{
id: "campaign-summary",
type: "folk-markdown",
x: col(0),
y: row(0) - 200,
width: 500,
height: 160,
rotation: 0,
content:
"# \ud83c\udf44 MycoFi Earth Launch Campaign\n\n**Duration:** Feb 21\u201325, 2026 (5 days)\n**Platforms:** X, LinkedIn, Instagram, YouTube, Threads, Bluesky\n**Posts:** 9 total across 3 phases\n\n| Phase | Days | Posts |\n|-------|------|-------|\n| Pre-Launch Hype | Day -3 to -1 | 3 posts |\n| Launch Day | Day 0 | 3 posts |\n| Amplification | Day +1 | 3 posts |",
},
// ────────────────────────────────────────────────────────────
// PHASE LABELS (markdown notes as section headers)
// ────────────────────────────────────────────────────────────
{
id: "label-phase1",
type: "folk-markdown",
x: col(1),
y: row(0) - 55,
width: COL_WIDTH * 3 + COL_GAP * 2,
height: 36,
rotation: 0,
content:
"### \ud83d\udce3 Phase 1: Pre-Launch Hype (Feb 21\u201323)",
},
{
id: "label-phase2",
type: "folk-markdown",
x: col(4),
y: row(0) - 85,
width: COL_WIDTH * 3 + COL_GAP * 2,
height: 36,
rotation: 0,
content: "### \ud83d\ude80 Phase 2: Launch Day (Feb 24)",
},
{
id: "label-phase3",
type: "folk-markdown",
x: col(7),
y: row(0) - 85,
width: COL_WIDTH * 3 + COL_GAP * 2,
height: 36,
rotation: 0,
content:
"### \ud83d\udce1 Phase 3: Amplification (Feb 25)",
},
// ────────────────────────────────────────────────────────────
// ARROWS (flow connections)
// ────────────────────────────────────────────────────────────
// Trigger → X Teaser
{
id: "arrow-trigger-to-teaser",
type: "folk-arrow",
x: 0,
y: 0,
width: 0,
height: 0,
rotation: 0,
sourceId: "campaign-trigger",
targetId: "post-x-teaser",
color: "#64748b",
},
// X Teaser → LinkedIn Thought Leadership
{
id: "arrow-teaser-to-linkedin",
type: "folk-arrow",
x: 0,
y: 0,
width: 0,
height: 0,
rotation: 0,
sourceId: "post-x-teaser",
targetId: "post-linkedin-thought",
color: "#0A66C2",
},
// LinkedIn Thought → IG Carousel
{
id: "arrow-linkedin-to-ig",
type: "folk-arrow",
x: 0,
y: 0,
width: 0,
height: 0,
rotation: 0,
sourceId: "post-linkedin-thought",
targetId: "post-ig-carousel",
color: "#E4405F",
},
// IG Carousel → YouTube Launch (phase transition)
{
id: "arrow-ig-to-yt",
type: "folk-arrow",
x: 0,
y: 0,
width: 0,
height: 0,
rotation: 0,
sourceId: "post-ig-carousel",
targetId: "post-yt-launch",
color: "#FF0000",
},
// YouTube → X Launch Thread
{
id: "arrow-yt-to-x-launch",
type: "folk-arrow",
x: 0,
y: 0,
width: 0,
height: 0,
rotation: 0,
sourceId: "post-yt-launch",
targetId: "post-x-launch",
color: "#000000",
},
// X Launch → LinkedIn Announcement
{
id: "arrow-x-to-linkedin-launch",
type: "folk-arrow",
x: 0,
y: 0,
width: 0,
height: 0,
rotation: 0,
sourceId: "post-x-launch",
targetId: "post-linkedin-launch",
color: "#0A66C2",
},
// LinkedIn Announcement → IG Reel (phase transition)
{
id: "arrow-linkedin-to-reel",
type: "folk-arrow",
x: 0,
y: 0,
width: 0,
height: 0,
rotation: 0,
sourceId: "post-linkedin-launch",
targetId: "post-ig-reel",
color: "#E4405F",
},
// IG Reel → Threads
{
id: "arrow-reel-to-threads",
type: "folk-arrow",
x: 0,
y: 0,
width: 0,
height: 0,
rotation: 0,
sourceId: "post-ig-reel",
targetId: "post-threads-xpost",
color: "#000000",
},
// Threads → Bluesky
{
id: "arrow-threads-to-bluesky",
type: "folk-arrow",
x: 0,
y: 0,
width: 0,
height: 0,
rotation: 0,
sourceId: "post-threads-xpost",
targetId: "post-bluesky-launch",
color: "#0085FF",
},
];
/**
* Ensure the campaign demo community exists and is seeded.
* Called on server startup alongside the main demo.
*/
export async function ensureCampaignDemo(): Promise<void> {
const slug = "campaign-demo";
const exists = await communityExists(slug);
if (!exists) {
await createCommunity(
"Social Media Campaign Demo",
slug,
null,
"public",
);
console.log(
"[Campaign] Created campaign-demo community with visibility: public",
);
} else {
await loadCommunity(slug);
}
// Check if already seeded
const data = getDocumentData(slug);
const shapeCount = data ? Object.keys(data.shapes || {}).length : 0;
if (shapeCount === 0) {
addShapes(slug, CAMPAIGN_SHAPES);
console.log(
`[Campaign] Seeded ${CAMPAIGN_SHAPES.length} shapes into campaign-demo`,
);
} else {
console.log(
`[Campaign] campaign-demo already has ${shapeCount} shapes`,
);
}
}