rspace-online/server/seed-campaign.ts

496 lines
15 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* 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... 🍄\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 🧵👇",
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 — 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 🌍🍄\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 — 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 — 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:
"🍄 MycoFi Earth is LIVE 🍄\n\nAfter 2 years of building, the regenerative finance platform is here.\n\nWhat is it?\n• Token-weighted funding circles\n• Mycelial governance (no whales)\n• Composting mechanism for failed proposals\n• 100% on-chain, 100% community-owned\n\n👇 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 — 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 ↓",
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 🍄✨\n\nVisual breakdown of the token flow from contributor → funding circle → project → 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 🌟\n\nThe idea is simple: what if finance worked like mycelium?\n\nMycelium doesn't hoard — it redistributes. MycoFi applies that logic to community funding.\n\nEarly access is open. Come grow with us 🌱",
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 🍄\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:
"# 🍄 MycoFi Earth Launch Campaign\n\n**Duration:** Feb 2125, 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:
"### 📣 Phase 1: Pre-Launch Hype (Feb 2123)",
},
{
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: "### 🚀 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:
"### 📡 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`,
);
}
}