///|
pub(all) struct CampaignPack {
name : String
description : String
jobs : Array[@config.PosterJob]
} derive(Debug, Eq)
///|
fn content(
eyebrow~ : String,
title~ : String,
subtitle~ : String,
body~ : String,
cta~ : String,
footer~ : String,
image_label~ : String,
image_asset_id~ : String,
) -> @template.TemplateContent {
{ eyebrow, title, subtitle, body, cta, footer, image_label, image_asset_id }
}
///|
fn job(
slug~ : String,
template~ : String,
preset~ : String,
theme~ : String,
content~ : @template.TemplateContent,
) -> @config.PosterJob {
{ slug, template, preset, theme, content }
}
///|
pub fn flatten_jobs(pack : CampaignPack) -> @config.BatchJob {
{ jobs: pack.jobs }
}
///|
pub fn hackathon_pack() -> CampaignPack {
{
name: "hackathon-showcase",
description: "Square launch, story editorial, and event card assets for a MoonBit hackathon sprint.",
jobs: [
job(
slug="launch-square",
template="launch",
preset="instagram-square",
theme="warm-editorial",
content=content(
eyebrow="MoonBit Hackathon 2026",
title="MoonBit PosterKit",
subtitle="Data-driven poster generation DSL",
body="Compose reusable layouts, typography, image slots, and presets with typed MoonBit APIs.",
cta="Build once, render everywhere",
footer="mooncakes.io / github",
image_label="Replace Cover Art",
image_asset_id="cover-art",
),
),
job(
slug="editorial-story",
template="editorial",
preset="social-story",
theme="swiss-grid",
content=content(
eyebrow="MoonBit Hackathon 2026",
title="Poster systems that stay programmable",
subtitle="A reusable visual language for release covers and social campaigns.",
body="Ship themed covers, editorial stories, and event visuals from one typed pipeline.",
cta="Readable, repeatable, release-ready",
footer="issue 01 / august / moonbit ecosystem",
image_label="Replace Story Image",
image_asset_id="story-art",
),
),
job(
slug="event-card",
template="event",
preset="instagram-square",
theme="warm-editorial",
content=content(
eyebrow="MoonBit Hackathon 2026",
title="Build Better Posters",
subtitle="Workshop / live coding / template walkthrough",
body="Share event details, code snippets, and social-ready visuals from one batch config.",
cta="August 2026 / online + on-site",
footer="Shanghai / livestream / moonbit-posterkit",
image_label="Replace Speaker Image",
image_asset_id="speaker-card",
),
),
],
}
}
///|
pub fn social_pack() -> CampaignPack {
{
name: "social-pack",
description: "Vertical stories for teasers and event promotion.",
jobs: [
job(
slug="teaser-story",
template="launch",
preset="social-story",
theme="swiss-grid",
content=content(
eyebrow="MoonBit PosterKit",
title="Launch visuals from typed configs",
subtitle="Create poster, story, and cover systems in MoonBit.",
body="Drive social packs from stable templates instead of manually editing each frame.",
cta="Batch render / swap content / keep hierarchy",
footer="template launch / preset social-story / theme swiss-grid",
image_label="Replace Teaser Image",
image_asset_id="teaser-image",
),
),
job(
slug="event-story",
template="event",
preset="social-story",
theme="swiss-grid",
content=content(
eyebrow="MoonBit Hackathon",
title="From config to campaign",
subtitle="A story-sized variant for fast event promotion.",
body="Use the same content model for vertical stories, squares, and wide thumbnails.",
cta="One content source / many aspect ratios",
footer="vertical social pack / automated output",
image_label="Replace Event Story Image",
image_asset_id="event-story",
),
),
],
}
}
///|
pub fn conference_pack() -> CampaignPack {
{
name: "conference-pack",
description: "A mixed asset family for CFP, keynote, and venue updates.",
jobs: [
job(
slug="cfp-square",
template="launch",
preset="instagram-square",
theme="swiss-grid",
content=content(
eyebrow="Conference Season",
title="Call for Papers",
subtitle="Typed templates for speakers, workshops, and programs.",
body="Keep hierarchy stable while swapping tracks, dates, and submission prompts.",
cta="Submit by September 15",
footer="cfp / workshops / lightning talks",
image_label="Replace CFP Image",
image_asset_id="cfp-image",
),
),
job(
slug="keynote-story",
template="editorial",
preset="social-story",
theme="swiss-grid",
content=content(
eyebrow="Keynote Feature",
title="Program systems that scale with your event",
subtitle="Editorial layouts for headliners, themes, and seasonal recaps.",
body="Highlight key speakers and topics without losing visual consistency.",
cta="Lineup reveal",
footer="conference / keynote / editorial story",
image_label="Replace Keynote Image",
image_asset_id="keynote-image",
),
),
job(
slug="venue-update",
template="event",
preset="instagram-square",
theme="warm-editorial",
content=content(
eyebrow="Venue Update",
title="One config, many event assets",
subtitle="Registration / venue / livestream / city guide",
body="Bundle operational updates into a repeatable event card system for teams.",
cta="Updated schedule / map / registration",
footer="venue hall b / streaming hall / city transit",
image_label="Replace Venue Image",
image_asset_id="venue-image",
),
),
],
}
}
///|
pub fn product_launch_pack() -> CampaignPack {
{
name: "product-launch-pack",
description: "A broad product release bundle spanning announcement, feature story, and webinar assets.",
jobs: [
job(
slug="launch-banner",
template="launch",
preset="youtube-thumbnail",
theme="swiss-grid",
content=content(
eyebrow="v0.1 release",
title="Ship launch banners from MoonBit",
subtitle="Widescreen visuals for video thumbnails and release announcements.",
body="Render hero headlines, feature teasers, and cover art slots without re-laying every asset.",
cta="Watch the release walkthrough",
footer="thumbnail / feature launch / video cover",
image_label="Replace Thumbnail Art",
image_asset_id="thumbnail-art",
),
),
job(
slug="feature-story",
template="editorial",
preset="social-story",
theme="warm-editorial",
content=content(
eyebrow="Feature Story",
title="PosterKit introduces reusable visual systems",
subtitle="Build and iterate release storytelling with typed inputs.",
body="Switch from ad-hoc design files to a structured pipeline that can be tested and automated.",
cta="Template-driven storytelling",
footer="release notes / cover story / product highlights",
image_label="Replace Feature Story Art",
image_asset_id="feature-story",
),
),
job(
slug="webinar-card",
template="event",
preset="instagram-square",
theme="swiss-grid",
content=content(
eyebrow="Launch Webinar",
title="Walk through the poster pipeline live",
subtitle="Batch config, template catalog, and CI in one session.",
body="Use event cards to promote demos, onboarding, and release education.",
cta="Register now / limited seats",
footer="launch webinar / q&a / sample walkthrough",
image_label="Replace Webinar Speaker",
image_asset_id="webinar-speaker",
),
),
],
}
}
///|
pub fn education_pack() -> CampaignPack {
{
name: "education-pack",
description: "Assets for tutorials, curriculum drops, and classroom updates.",
jobs: [
job(
slug="curriculum-square",
template="launch",
preset="instagram-square",
theme="warm-editorial",
content=content(
eyebrow="Course Drop",
title="Teach visual systems with typed examples",
subtitle="Students can read code, templates, and rendered outputs side by side.",
body="Package lesson visuals, worksheet covers, and class announcements in one MoonBit module.",
cta="New lesson bundle available",
footer="education / typed examples / reusable assets",
image_label="Replace Curriculum Art",
image_asset_id="curriculum-art",
),
),
job(
slug="lecture-story",
template="editorial",
preset="social-story",
theme="swiss-grid",
content=content(
eyebrow="Lecture Story",
title="Design systems as executable examples",
subtitle="Explain hierarchy, spacing, and reuse with renderable code.",
body="Story layouts turn code-driven templates into a teaching artifact, not just a build output.",
cta="Lecture week 03",
footer="visual systems / classroom / story lesson",
image_label="Replace Lecture Image",
image_asset_id="lecture-image",
),
),
job(
slug="office-hours",
template="event",
preset="instagram-square",
theme="warm-editorial",
content=content(
eyebrow="Office Hours",
title="Bring your template and batch config questions",
subtitle="Mentoring / lab help / rendering clinic",
body="Event assets keep support sessions and workshop reminders consistent across weeks.",
cta="Fridays / 19:00 / online",
footer="office hours / review / support",
image_label="Replace Tutor Photo",
image_asset_id="tutor-photo",
),
),
],
}
}
///|
pub fn community_pack() -> CampaignPack {
{
name: "community-pack",
description: "Community spotlights, weekly digests, and member-driven announcements.",
jobs: [
job(
slug="weekly-digest",
template="launch",
preset="instagram-square",
theme="swiss-grid",
content=content(
eyebrow="Community Weekly",
title="What the MoonBit ecosystem shipped this week",
subtitle="Round up packages, talks, and examples with stable layouts.",
body="Digest cards help community maintainers summarize wins without redoing design decisions.",
cta="Read the full roundup",
footer="weekly digest / ecosystem / examples",
image_label="Replace Digest Art",
image_asset_id="digest-art",
),
),
job(
slug="member-story",
template="editorial",
preset="social-story",
theme="warm-editorial",
content=content(
eyebrow="Builder Spotlight",
title="How contributors turn templates into momentum",
subtitle="Story assets for maintainers, talks, and open source spotlights.",
body="Promote community stories with a reusable editorial layout that keeps typography consistent.",
cta="Member story / spotlight / notes",
footer="community / spotlight / august",
image_label="Replace Member Portrait",
image_asset_id="member-portrait",
),
),
],
}
}
///|
pub fn quote_story_pack() -> CampaignPack {
{
name: "quote-story-pack",
description: "Thought leadership cards, founder quotes, and speaker portraits for social campaigns.",
jobs: [
job(
slug="founder-quote",
template="quote",
preset="instagram-square",
theme="warm-editorial",
content=content(
eyebrow="Builder Quote",
title="Design systems become momentum once they can be reused and reviewed in code.",
subtitle="MoonBit Community",
body="Pair structured layouts with typed content so quotes, promos, and recaps all stay consistent.",
cta="Share the idea / keep the voice",
footer="quote card / portrait / social square",
image_label="Replace Founder Portrait",
image_asset_id="founder-portrait",
),
),
job(
slug="speaker-portrait-story",
template="quote",
preset="social-story",
theme="swiss-grid",
content=content(
eyebrow="Speaker Note",
title="Templates are most useful when they survive edits, handoffs, and release pressure.",
subtitle="Hackathon Workshop Host",
body="Use the same content schema for square pull quotes, story slides, and event-side speaker cards.",
cta="Story portrait / event teaser",
footer="quote story / portrait / swipes",
image_label="Replace Speaker Portrait",
image_asset_id="speaker-portrait",
),
),
],
}
}
///|
pub fn weekly_digest_pack() -> CampaignPack {
{
name: "weekly-digest-pack",
description: "Weekly recaps, release summaries, and multi-item campaign digest assets.",
jobs: [
job(
slug="release-digest-wide",
template="digest",
preset="youtube-thumbnail",
theme="swiss-grid",
content=content(
eyebrow="Weekly Digest",
title="What shipped in MoonBit PosterKit this week",
subtitle="Templates, validation, and CLI output all matured together.",
body="Summarize releases, docs, and examples with a repeatable format that teams can batch render.",
cta="Open the changelog",
footer="digest / release / weekly recap",
image_label="Replace Digest Cover",
image_asset_id="digest-cover",
),
),
job(
slug="feature-digest-square",
template="digest",
preset="instagram-square",
theme="warm-editorial",
content=content(
eyebrow="Feature Digest",
title="One content source, many aspect ratios",
subtitle="Square and wide digest cards can share the same structure.",
body="Turn summary-heavy announcements into reusable visual blocks that still read clearly at a glance.",
cta="Read the recap",
footer="feature digest / square card / release notes",
image_label="Replace Feature Digest Art",
image_asset_id="feature-digest-art",
),
),
job(
slug="community-digest-story",
template="digest",
preset="social-story",
theme="swiss-grid",
content=content(
eyebrow="Community Digest",
title="Ecosystem highlights, talks, and maintainers in one visual summary",
subtitle="Story-sized weekly roundups for maintainers and community editors.",
body="Batch render digest slides for stories, recap threads, and event newsletters from the same typed data.",
cta="Swipe the highlights",
footer="story digest / ecosystem / roundup",
image_label="Replace Community Digest Art",
image_asset_id="community-digest-art",
),
),
],
}
}
///|
pub fn release_notes_pack() -> CampaignPack {
{
name: "release-notes-pack",
description: "A release-note oriented set that mixes thumbnails, social squares, and event reminders.",
jobs: [
job(
slug="release-thumbnail",
template="launch",
preset="youtube-thumbnail",
theme="warm-editorial",
content=content(
eyebrow="Release Notes",
title="What changed in MoonBit PosterKit",
subtitle="Thumbnail-first visuals for changelogs and walkthrough videos.",
body="Highlight the biggest additions, template updates, and rendering improvements for each release.",
cta="Watch the changelog",
footer="release notes / walkthrough / thumbnail",
image_label="Replace Release Thumbnail",
image_asset_id="release-thumb",
),
),
job(
slug="release-square",
template="launch",
preset="instagram-square",
theme="swiss-grid",
content=content(
eyebrow="Version 0.1.0",
title="Built-in templates, config batches, and CLI output",
subtitle="A square announcement asset for social timelines.",
body="Keep release communication aligned across channels with template-aware composition.",
cta="Read the changelog",
footer="v0.1.0 / release / social",
image_label="Replace Release Art",
image_asset_id="release-art",
),
),
job(
slug="release-demo-event",
template="event",
preset="instagram-square",
theme="swiss-grid",
content=content(
eyebrow="Live Demo",
title="See the new batch renderer in action",
subtitle="Demo / Q&A / roadmap",
body="Promote release sessions and roadmap talks with the same event layout used for workshops.",
cta="Thursday / 20:00 / live",
footer="demo stream / release week / roadmap",
image_label="Replace Release Speaker",
image_asset_id="release-speaker",
),
),
],
}
}
///|
pub fn release_note_pack() -> CampaignPack {
{
name: "release-note-pack",
description: "Release notes, upgrade highlights, and changelog visuals for community projects.",
jobs: [
job(
slug="release-note-card",
template="digest",
preset="instagram-square",
theme="swiss-grid",
content=content(
eyebrow="Release Notes",
title="What changed this week",
subtitle="Highlights for maintainers and users",
body="Summarize fixes, features, and migration notes in one repeatable visual card.",
cta="Read the changelog",
footer="release notes / upgrade / community",
image_label="Replace Release Art",
image_asset_id="release-note-art",
),
),
],
}
}
///|
pub fn community_digest_pack() -> CampaignPack {
{
name: "community-digest-pack",
description: "Weekly community digests for packages, talks, examples, and contributor stories.",
jobs: [
job(
slug="community-digest-card",
template="digest",
preset="social-story",
theme="warm-editorial",
content=content(
eyebrow="Community Digest",
title="What the ecosystem shipped",
subtitle="Packages, talks, and examples",
body="Collect the week’s most useful community updates into a story-ready summary.",
cta="Explore the roundup",
footer="weekly digest / ecosystem / contributors",
image_label="Replace Digest Art",
image_asset_id="community-digest-art",
),
),
],
}
}
///|
pub fn event_announcement_pack() -> CampaignPack {
{
name: "event-announcement-pack",
description: "Event announcements for workshops, livestreams, meetups, and community sessions.",
jobs: [
job(
slug="event-announcement-card",
template="event",
preset="instagram-square",
theme="warm-editorial",
content=content(
eyebrow="Community Event",
title="Build and share together",
subtitle="Workshop / livestream / Q&A",
body="Publish event details with stable hierarchy for schedules, venues, and registration prompts.",
cta="Register now",
footer="event / workshop / livestream",
image_label="Replace Event Art",
image_asset_id="event-announcement-art",
),
),
],
}
}
///|
pub fn project_spotlight_pack() -> CampaignPack {
{
name: "project-spotlight-pack",
description: "Project spotlights for open source tools, maintainers, technical tags, and contribution links.",
jobs: [
job(
slug="project-spotlight-card",
template="editorial",
preset="social-story",
theme="swiss-grid",
content=content(
eyebrow="Project Spotlight",
title="A closer look at a MoonBit project",
subtitle="Architecture / use cases / contributors",
body="Explain a project’s value and contribution path with a reusable editorial composition.",
cta="Explore the repository",
footer="open source / spotlight / maintainers",
image_label="Replace Project Art",
image_asset_id="project-spotlight-art",
),
),
],
}
}
///|
pub fn all_packs() -> Array[CampaignPack] {
[
hackathon_pack(),
social_pack(),
conference_pack(),
product_launch_pack(),
education_pack(),
community_pack(),
quote_story_pack(),
weekly_digest_pack(),
release_notes_pack(),
release_note_pack(),
community_digest_pack(),
event_announcement_pack(),
project_spotlight_pack(),
]
}