Self-Media Composer Skill
Complete capability for building and managing self-media projects. One project groups many posts; each post is an independent folder with its own meta and card sequence. This skill scaffolds that structure, authors the cards, generates reference engagement data, and keeps the root index in sync.
When to Load This Skill
Load this skill immediately and before any other action when the user's message matches any of the following patterns.
English
| User says |
Load reason |
| "create a post" / "add a post" |
New post creation |
| "make cards for Rednote / Instagram" |
Card-based post authoring |
| "write a WeChat article" / "WeChat official account post" |
Article post authoring |
| "build a self-media project" / "start a content project" |
Project scaffolding |
| "generate social cards" / "design card images" |
Card design |
| "create content for [platform]" |
Any platform post |
| "post-publication review" / "article ops review" |
Operations data sync |
| "fetch published data" / "update ops files" |
Operations data sync |
| "sync now" / "real data refresh" |
Operations data sync |
Contains [@self_media_project:...] |
Existing project reference |
Multilingual
Load for equivalent requests in any user language, including Chinese-language requests for Xiaohongshu/Rednote posts, WeChat Official Account articles, Instagram cards, card-based social posts, content projects, publishing-data import, immediate sync, real data refresh, operations review, or any message containing [@self_media_project:...].
Note: When localized platform aliases appear, treat them as the corresponding platform values. See Platform Aliases in the Platform Defaults section.
Execution
All Python snippets in this document must run through run_sdk_snippet:
run_sdk_snippet(
python_code="""
from sdk.tool import tool
result = tool.call('create_self_media_project', {
'project_path': 'ai-monthly',
'platform': 'rednote'
})
print(result)
"""
)
result exposes result.ok, result.content, result.data. Access structured data via result.data; the object is not subscriptable.
Output Language Contract
The skill documentation is written in English, but generated content must adapt to the user's language.
- Infer the user's preferred output language from the current user message first, then from active draft content, existing post language, project context, and explicit platform requirements. If the target language is still ambiguous and the choice affects the final content, ask one concise clarification.
- Write all user-facing text in the inferred language: questions, option labels, project/post display names, titles, subtitles, card copy, article prose, captions, comments, CTA text, placeholder labels, relative time strings, operations review prose, and template descriptions.
- Keep machine contracts stable: platform values, preset IDs, JSON keys, enum values, CSS class names, JS namespaces, file extensions, and API/tool parameters stay in their documented form.
- Use safe filesystem IDs. Prefer lowercase ASCII slugs for
project_path, post_id, card filenames, and preset names unless the user explicitly needs localized filenames and the path is safe.
- Do not translate brand names, platform names, product names, source quotes, code identifiers, or fixed schema values. Translate surrounding explanation and content intent.
- For Rednote tags, choose tags that fit the user's output language and the platform's search behavior. The Chinese hashtag library is a reference set for Chinese/Xiaohongshu SEO, not a command to force Chinese tags in non-Chinese output.
- Set HTML
lang attributes to the inferred language when writing cards or articles (zh-CN, en, ja, etc.).
Project Concept
A self-media project is a Magic Project folder whose magic.project.js declares type: "self-media". It contains:
magic.project.js at the root — JSONP, holds a per-platform posts index
posts/<post-id>/ — one folder per post, fully self-contained
shared/ — optional, assets shared across posts (including copied preset bundles)
Directory layout:
<project-root>/
├── magic.project.js
├── posts/
│ ├── <post-id>/
│ │ ├── post.json
│ │ ├── cards/ # rednote / instagram only
│ │ │ ├── <card>.html
│ │ │ └── ...
│ │ └── assets/
│ ├── <wechat-post-id>/ # wechat-official-accounts
│ │ ├── post.json
│ │ ├── <article>.html # single article HTML
│ │ └── assets/
│ │ ├── cover-hero.jpg
│ │ └── cover-square.jpg
│ └── ...
└── shared/
└── presets/
└── <preset-name>/
├── <preset-name>.css
└── <preset-name>.js
Preset source files (inside this skill) are organized by platform:
presets/
├── rednote/
│ ├── neo-brutalism/
│ ├── code-dispatch/
│ ├── dark-tech/
│ ├── gradient-editorial/
│ ├── personal-insight/
│ ├── film-vintage/
│ ├── warm-journal/
│ ├── paper-column/
│ ├── signal-grid/
│ └── product-launch-preset/
├── instagram/
│ ├── ins-modern/
│ ├── ins-minimal/
│ ├── ins-dark/
│ ├── ins-retro/
│ ├── ins-fluent-depth/
│ ├── ins-token-system/
│ ├── ins-creator-studio/
│ ├── ins-film-frame/
│ ├── ins-warm-journal/
│ └── ins-signal-grid/
└── wechat-official-accounts/
└── (coming soon)
For magic.project.js and post.json format examples, path rules, and file authoring rules, see references/file-formats.md.
File authoring rules (summary)
magic.project.js must be generated by create_self_media_project. Never create or overwrite it with write_file. Edit its inner posts array via edit_file only.
post.json is produced by create_self_media_post. Edit it with edit_file for subsequent changes.
- Card HTML files can be authored directly with
write_file.
Platform Defaults
Currently supported platform values: rednote, instagram, wechat-official-accounts.
Platform Aliases
| User says |
Maps to platform |
| 微信公众号 / 公众号 / 微信公众账号 |
wechat-official-accounts |
| 小红书 / 红书 / RED |
rednote |
| ins / Instagram |
instagram |
When the user mentions any localized alias above, treat it as the corresponding platform value without asking for clarification. Keep the canonical platform values in files and tool calls.
The table below is a fallback only. When the user explicitly specifies card size or aspect ratio, follow the user's values; do not override them with the defaults.
| platform |
Default size |
Aspect |
Notes |
rednote |
540x720 |
3:4 |
Xiaohongshu vertical card, standard feed |
instagram |
540x675 |
4:5 |
Instagram feed portrait |
wechat-official-accounts |
N/A |
N/A |
Article post: single HTML + heroCover + thumbnailCover |
Fallback rules inside instagram: if the user wants a square layout, use 540x540 (1:1); for stories or reels covers, use 540x960 (9:16). Ask before assuming.
Decision order every time you pick a card canvas size:
- If the user specified a size or aspect ratio in the current session, use it.
- Else, if the user specified only a platform, use the platform default from the table above.
- Else, ask the user which platform and size they want before starting.
Built-in Presets
Presets are organized by platform under presets/<platform>/<preset>/. Each preset is a pair of files (<preset>.css + <preset>.js).
| Platform |
Preset |
Style summary |
rednote |
neo-brutalism |
Neo-Brutalism: thick black borders, hard offset shadows, saturated palette. |
rednote |
code-dispatch |
Code Dispatch: high-contrast editorial style, black/white/red palette, monospace labels, no rounded corners, grid background texture. Best for tech/coding/AI topics. |
rednote |
dark-tech |
Dark-Tech: deep black background, gold accent, thin 1px borders, heavy/light font-weight contrast. Inspired by DJI-style review cards. Best for product/gear reviews. |
rednote |
gradient-editorial |
Image Editorial: cover uses hero/theme image with gradient overlay for text readability, clean white content pages, rounded cards. Best for AI/tech insight articles. |
rednote |
personal-insight |
Personal Insight: clean white background, profile avatar, numbered sections, reading-note style. Best for personal reflections and knowledge sharing. |
rednote |
film-vintage |
Film Vintage: dark cinematic cover, polaroid-style photo frames, mono grain texture, red accent, serif+mono typography. Best for film photography, gear reviews, and city walk journals. |
rednote |
warm-journal |
Warm Journal: photo-led journal pages, handwritten titles, khaki/beige paper textures, scattered notes, and polaroid frames. Best for lifestyle, product notes, and city records. |
rednote |
paper-column |
Paper Column: paper texture, serif display titles, marginal notes, pull quotes, ledgers, and evidence frames. Best for essays, analysis, knowledge columns, and field-note narratives. |
rednote |
signal-grid |
Signal Grid: strict grid rhythm, light display type, one accent color, matrix rows, KPI blocks, and ranking bars. Best for product notes, comparisons, launch explainers, and structured decisions. |
rednote |
product-launch-preset |
Product Launch: white background, 6px red top accent bar, black text + red highlights only, sharp 2px badges, 10px rounded image containers. Best for product feature announcements and release notes. |
instagram |
ins-modern |
Instagram Modern: bold white editorial cards, crisp black structure, hard shadows, and selective social accents. Best for creator productivity and punchy carousel hooks. |
instagram |
ins-minimal |
Instagram Minimal: quiet premium whitespace, fine rules, serif display type, and calm editorial hierarchy. Best for digests, summaries, and point-of-view posts. |
instagram |
ins-dark |
Instagram Dark Tech: dark product-launch energy, electric accents, console-like modules, and high-contrast data blocks. Best for tools, productivity, and technical topics. |
instagram |
ins-retro |
Instagram Retro Story: warm paper, stamp details, ornamental rules, and story-first pacing. Best for storytelling content and visual guides. |
instagram |
ins-fluent-depth |
Instagram Fluent Depth: soft layered surfaces, restrained depth, calm material feel, and readable product storytelling. Best for workflow explainers and high-trust product stories. |
instagram |
ins-token-system |
Instagram Token System: neutral surfaces, semantic color roles, compact lozenges, and enterprise grid rhythm. Best for structured decisions and product comparisons. |
instagram |
ins-creator-studio |
Instagram Creator Studio: profile-led structure, numbered lessons, credibility blocks, and personal voice cues. Best for personal insights and creator education. |
instagram |
ins-film-frame |
Instagram Film Frame: cinematic black frame, contact-sheet rhythm, warm highlights, and review-ready panels. Best for photography, gear reviews, and city walk journals. |
instagram |
ins-warm-journal |
Instagram Warm Journal: soft journal pages, taped-note modules, warm accents, and lifestyle-friendly grids. Best for lifestyle notes, product diaries, and cozy recommendations. |
instagram |
ins-signal-grid |
Instagram Signal Grid: strict grid rhythm, matrix rows, KPI cells, and decision-oriented comparison blocks. Best for product comparisons, launch explainers, and structured decisions. |
wechat-official-accounts |
(coming soon) |
Presets for WeChat article style will be added here. |
Source paths inside this skill:
presets/rednote/neo-brutalism/neo-brutalism.{css,js}
presets/rednote/code-dispatch/code-dispatch.{css,js}
presets/rednote/dark-tech/dark-tech.{css,js}
presets/rednote/gradient-editorial/gradient-editorial.{css,js}
presets/rednote/personal-insight/personal-insight.{css,js}
presets/rednote/film-vintage/film-vintage.{css,js}
presets/rednote/warm-journal/warm-journal.{css,js}
presets/rednote/paper-column/paper-column.{css,js}
presets/rednote/signal-grid/signal-grid.{css,js}
presets/rednote/product-launch-preset/product-launch.{css,js}
presets/instagram/ins-modern/ins-modern.{css,js}
presets/instagram/ins-minimal/ins-minimal.{css,js}
presets/instagram/ins-dark/ins-dark.{css,js}
presets/instagram/ins-retro/ins-retro.{css,js}
presets/instagram/ins-fluent-depth/ins-fluent-depth.{css,js}
presets/instagram/ins-token-system/ins-token-system.{css,js}
presets/instagram/ins-creator-studio/ins-creator-studio.{css,js}
presets/instagram/ins-film-frame/ins-film-frame.{css,js}
presets/instagram/ins-warm-journal/ins-warm-journal.{css,js}
presets/instagram/ins-signal-grid/ins-signal-grid.{css,js}
When the user picks a preset (see Workflow Step 4.1), read the source files from presets/<platform>/<preset>/ and copy both files once into the project at shared/presets/<preset>/. Reference them from every card with <link> and <script> tags using ../../../shared/presets/<preset>/<preset>.css|.js.
Custom Preset Generation (Optional Sub-Skill)
When the user wants a visual style that is not covered by any built-in preset, a custom preset can be generated from a free-form description. This capability is encapsulated in the generate-preset sub-skill:
generate-preset/SKILL.md (inside this skill folder)
Load this sub-skill when:
- The user selects "Custom style" in the Step 4.1 picker.
- The user explicitly asks to "create a new preset", "design a theme", or "generate a style".
- The user provides a reference image / Figma frame and asks for a matching preset.
What it produces: a <preset-name>.css + <preset-name>.js pair, saved to <project-root>/shared/presets/<preset-name>/, ready to be linked from cards exactly like a built-in preset.
Core Tools
create_self_media_project
Scaffolds a new self-media project. Creates the project folder, posts/, shared/, and a valid magic.project.js. It does not generate any frontend loader HTML - rendering lives in other frontends.
| Parameter |
Required |
Description |
project_path |
Yes |
Project folder path, workspace-relative. Reflect the topic; prefer a safe ASCII slug unless the user explicitly needs a localized filesystem name. |
platform |
Yes |
One of rednote, instagram, wechat-official-accounts. |
posts |
No |
Optional pre-registered post index entries. Each item { "id": "...", "name": "..." }. Default []. |
Returns: { project_path, project_name, platform, posts_count }.
create_self_media_post
Creates a single post directory (posts/<post_id>/) with post.json and an empty assets/. For card-based platforms (rednote / instagram) also creates an empty cards/. Optionally registers the post in the root magic.project.js posts array of the project's platform.
| Parameter |
Required |
Description |
project_path |
Yes |
Self-media project root, workspace-relative. |
post_id |
Yes |
Stable id, safe for filesystem (for example ai-bill). Used as folder name and post.json.id. |
post_name |
Yes |
Display name written into the root posts[] entry and as the fallback meta.title. |
meta |
No |
Object merged into post.json.meta. Free-form fields: title, subtitle, tags, author, feedTitle, feedLikes, commentCount, comments, time (wechat), interactionReference, etc. For rednote, tags should use the structured hashtag pyramid unless the user supplied a legacy string/array format. |
cards |
No |
rednote / instagram only. Initial value for post.json.cards. Paths relative to the post folder, for example "cards/01.html". |
article |
No |
wechat-official-accounts only. Relative path to the single HTML article file, for example "my-article.html". When provided, the post is treated as a WeChat article post; cards is ignored. |
hero_cover |
No |
wechat-official-accounts only. Relative path to the hero cover image (21:9), for example "assets/cover-hero.jpg". Written as heroCover in post.json. |
thumbnail_cover |
No |
wechat-official-accounts only. Relative path to the square thumbnail cover image, for example "assets/cover-square.jpg". Written as thumbnailCover in post.json. |
register_in_project |
No |
Default true. Append/update the entry in the root magic.project.js posts array. If the frontend prompt says the post is already pre-registered, explicitly pass false and do not edit the root index. |
Idempotence: if posts/<post_id>/ already exists, the tool merges meta (shallow merge, new keys win), keeps existing cards / article / heroCover / thumbnailCover untouched unless the caller passes new values, and preserves the root posts entry order.
Returns: { post_path, post_json_path, registered }.
Workflow
Follow this loop until the user's intent is fully served.
Step 0 - check for existing planning data (automatic)
Before asking any questions, check if the project already contains user planning data from the frontend:
- Look for
__drafts/draft.json in the self-media folder.
- If found,
read_files to load it. See Drafts & Templates Format for the schema.
- If
__drafts/reference-index.json exists, read it immediately after draft.json. Treat it as the unified reference entry point.
- If brand context is needed and
draft.json.global is missing, sparse, or stale, try to read __brand/brand-config.json before asking the user. Treat it as an optional fallback. Current-session user instructions and explicit draft.json.global values outrank it.
- Extract and apply context:
global.author / global.brandPosition / global.targetAudience → brand context (no need to ask)
global.brandImages → brand IP image assets for image generation reference (use in Step 4.3)
__brand/brand-config.json fields → brand context fallback when global fields are unavailable
articles[].title / articles[].outline → content structure is pre-planned
articles[].visualPreset → visual preset is pre-selected (skip Step 4.1 for that article)
articles[].style → content tone is chosen
articles[].platform → known platform for that article
articles[].materials → article-level reference files available via relativePath
articles[].outline[].materials → node-scoped reference files available via relativePath
articles[].visualReferenceFiles → visual-style references available via file_path or inline content
articles[].notes → explicit user instructions to follow
articles[].cardCount → target card count
- Read and understand all uploaded references before drafting, designing, or generating images. This rule applies regardless of where the user attached the file in the frontend.
- If the draft provides enough information to proceed (at least one article with title plus either platform or clear continuation context), skip directly to the appropriate step. If the draft is incomplete, proceed from Step 1 but pre-fill known fields.
This step is silent — do not announce "I found a draft" unless the data is ambiguous and needs user confirmation.
Step 0.1 - read uploaded references before creation
This step is mandatory whenever uploaded references exist.
- Resolve references from
reference-index.json first.
- If
reference-index.json is missing or incomplete, fall back to:
__brand/brand-config.json, when brand context is needed
global.brandImages
articles[].materials
articles[].outline[].materials
articles[].visualReferenceFiles
- Resolve each reference in this order:
relativePath
file_path / file_id
- inline
content
- Read and understand the reference before drafting copy, generating images, or designing cards.
- Group the references by role:
brand
article-material
outline-material
visual-reference
- Apply them at the correct scope. Outline-node references should influence the matching node first, not the whole post by default.
- If a reference cannot be fully read, do not ignore it. State the limitation explicitly and still use its name, description, path, and surrounding context.
Step 1 - understand intent and platform
- Clarify the topic and target platform. If platform or content type is missing, ask one question before proceeding.
- For
wechat-official-accounts: the post is a single long-form HTML article plus two cover images — not a card sequence.
- For
rednote / instagram: the post is a sequence of fixed-size card HTML files.
- Outline how many posts the request implies, and for each post the rough number of cards (or confirm it is a single article for WeChat).
Step 2 - research factual content (when needed)
- Use
web_search and read_webpages_as_markdown to gather up-to-date facts, data points, quotes, or source material for the copy.
- Always incorporate the uploaded references from Step 0.1 before expanding with external research. Uploaded references outrank generic web research when they cover the same topic.
- Do not search or generate images in this step. Images must serve the visual language, and the visual language is only fixed in Step 4.1. Collecting or generating images before the style is resolved will force the cards to accommodate mismatched visuals instead of the other way around.
Step 3 - scaffold the project (first time only)
- Call
create_self_media_project with project_path and platform.
- Optionally pass
posts=[{id, name}, ...] if you already know the full post list.
Step 4 - author each post
For every post, run this ordered sub-flow. Do not skip or reorder steps.
Before running 4.1-4.5 for a post, confirm that you have already read and understood:
- article-level materials for that post
- outline-node materials for that post
- visual reference files for that post
- any brand image assets that influence stylistic or brand consistency
4.1 Ask the user which preset to use (mandatory for all platforms)
Before creating any post content, call ask_user exactly once and let the user pick the visual template. Render the question and option labels in the user's preferred output language while keeping the canonical preset IDs unchanged. Present only the presets available for the current platform, plus an explicit "No template" option:
For rednote:
<question type="select">
Please choose a visual template for the cards:
<option>neo-brutalism — thick black borders, hard offset shadows, saturated palette</option>
<option>code-dispatch — high-contrast editorial, black/white/red, monospace labels, grid texture; ideal for tech/coding/AI topics</option>
<option>dark-tech — deep black background, gold accent, thin borders, DJI-style; ideal for product/gear reviews</option>
<option>gradient-editorial — hero image with gradient overlay, clean white content pages, modern editorial style; ideal for AI/tech insight articles</option>
<option>personal-insight — clean white background, profile avatar, numbered sections; ideal for personal reflections and knowledge sharing</option>
<option>film-vintage — cinematic cover, polaroid photo frames, grain texture, red accent; ideal for photography, gear reviews, and city walks</option>
<option>warm-journal — photo-led journal pages, handwritten titles, khaki/beige paper textures; ideal for lifestyle, product notes, and city records</option>
<option>paper-column — paper texture, serif titles, marginal notes, pull quotes, and ledgers; ideal for essays, analysis, and knowledge columns</option>
<option>signal-grid — strict grid rhythm, one accent color, KPI blocks, matrix rows, and ranking bars; ideal for comparisons, product notes, and decisions</option>
<option>product-launch-preset — white background, red top accent bar, sharp badges, minimal dual-color; ideal for product feature announcements and release notes</option>
<option>Custom style — describe the visual language you want and a preset will be generated for you</option>
<option>No template — design freely following the platform baseline</option>
</question>
For instagram:
<question type="select">
Please choose a visual template for the cards:
<option>ins-modern — white background, generous whitespace, minimal typography</option>
<option>ins-minimal — restrained whitespace, fine dividers, minimal hierarchy; ideal for digests and summary posts</option>
<option>ins-dark — dark tech styling, neon accents, high-contrast modules; ideal for tools, productivity, and technical topics</option>
<option>ins-retro — retro headlines, warm paper tones, ornamental marks; ideal for storytelling and visual guides</option>
<option>ins-fluent-depth — soft layered surfaces, restrained depth, calm product storytelling; ideal for workflow explainers and product stories</option>
<option>ins-token-system — neutral surfaces, semantic color roles, compact lozenges, enterprise grid rhythm; ideal for product comparisons and structured decisions</option>
<option>ins-creator-studio — profile-led lessons, credibility blocks, personal voice cues; ideal for creator education and reflections</option>
<option>ins-film-frame — cinematic frame, contact-sheet rhythm, warm highlights; ideal for photography, gear reviews, and city walks</option>
<option>ins-warm-journal — soft journal pages, taped-note modules, warm lifestyle grids; ideal for product notes and cozy recommendations</option>
<option>ins-signal-grid — strict grid rhythm, KPI cells, matrix rows; ideal for comparisons, launch explainers, and decisions</option>
<option>Custom style — describe the visual language you want and a preset will be generated for you</option>
<option>No template — design freely following the platform baseline</option>
</question>
For wechat-official-accounts:
<question type="select">
Please choose a visual template for the article:
<option>Custom style — describe the visual language you want and a preset will be generated for you</option>
<option>No template — design freely following the WeChat article baseline (presets coming soon)</option>
</question>
Rules:
- Do not skip this prompt for any platform — even when the user already described a style vaguely, the preset choice must be explicit.
- If the user picks a built-in preset, read the source files from
presets/<platform>/<preset>/ inside this skill and copy them into the project once:
- source:
presets/<platform>/<preset>/<preset>.css and presets/<platform>/<preset>/<preset>.js.
- destination:
<project-root>/shared/presets/<preset>/<preset>.css and <preset>.js.
- Use
read_files to load the sources and write_file to copy; skip the copy if the destination already exists.
- If the user picks Custom style, ask a follow-up free-text question:
<question type="text">
Describe the visual style you want (e.g. mood, colors, font feel, decoration, content domain):
</question>
Then load and follow the generate-preset sub-skill (generate-preset/SKILL.md inside this skill folder) to generate a custom CSS + JS preset bundle. Save the generated files to <project-root>/shared/presets/<preset-name>/ before proceeding to Step 4.2. Treat the generated preset exactly like a built-in preset for all subsequent card authoring steps.
- If the user picks No template, go straight to 4.2 without copying anything; content will be authored against the plain platform defaults.
- When the user explicitly provides their own HTML template, screenshot, Figma link, or CSS spec in this session, that artifact outranks the preset choice. You may still copy a preset in parallel for icon/helper utilities, but layout and colors must follow the user artifact.
4.2 Create the post folder
Before calling create_self_media_post, generate a complete meta object from the planned article/card content. Besides title, subtitle, tags, author, and feed title, every new post must include reference engagement data:
feedLikes: a platform-appropriate display string, such as "1.8w", "12.3k", or "860".
commentCount: a display string aligned with feedLikes and the likely engagement level.
comments: 3-5 plausible sample evaluations for every generated post, written in the audience's voice and tied to the actual content. Rednote / Instagram previewers render them; WeChat stores them as a reference evaluation pool. Do not use generic praise such as "Great post".
time: for wechat-official-accounts, a natural relative feed time in the user's output language, such as "4 minutes ago" or the localized equivalent.
interactionReference: optional but recommended. Use it for non-rendered notes such as { "level": "medium-high", "basis": "product launch / strong pain point", "disclaimer": "reference display data, not real platform analytics" }.
Treat these numbers and evaluations as reference/display data, not verified analytics. They should feel credible for the platform, topic, audience size, and content intensity; do not invent factual performance claims such as "real launch data" unless the user supplied the data.
4.2.1 Build meta.tags for rednote
For every rednote post, load Rednote Hashtag Library before calling create_self_media_post. Populate meta.tags with the four-layer pyramid:
{
"core": ["workwear"],
"mid": ["commute outfits", "petite styling"],
"longtail": ["outfits for new office workers", "155cm styling tips"],
"trend": ["dopamine dressing"]
}
Rules:
- Total count must be 5-8 tags. Hard cap: 10.
- Output order is
core -> mid -> longtail -> trend.
core: 1-2 category anchors.
mid: 2-3 scenario, style, or search-intent tags.
longtail: 2-3 audience, pain-point, location, body-type, budget, or use-case tags.
trend: 0-1 current trend or official activity tag. Omit stale trend tags.
- Travel posts must include a concrete city, area, route, or attraction tag.
- If the user supplies tags as a string or array, preserve them only when they are relevant and within the cap; otherwise normalize them into the four fields and remove off-topic tags.
- If the topic is outside the built-in categories, build the same four layers from the post's audience, scenario, pain point, and trend. Do not force a mismatched category from the library.
🔴 CHECKPOINT · Rednote tag confirmation:
- If the user did not provide tags, propose the final 5-8 tags once before creating the post.
- If a draft or frontend planning payload already contains tag intent, use it as the source of truth and do not ask again unless the tags violate the cap, contain irrelevant traffic-bait, or miss a required concrete qualifier such as a travel location.
For rednote / instagram: call create_self_media_post with post_id, post_name, the complete meta, and the planned cards list. This yields posts/<id>/post.json, cards/, and assets/. If the frontend prompt states that the post was pre-registered in magic.project.js, pass register_in_project=false.
For wechat-official-accounts: call create_self_media_post with post_id, post_name, the complete meta, article (the filename), hero_cover (e.g. "assets/cover-hero.jpg"), and thumbnail_cover (e.g. "assets/cover-square.jpg"). This yields posts/<id>/post.json and assets/. No cards/ folder is created. If the frontend prompt states that the post was pre-registered in magic.project.js, pass register_in_project=false.
4.3 Collect or generate images (after the style is fixed)
Only after the preset decision in 4.1 is done are images allowed to enter the pipeline. Images serve the style; never let images dictate it.
4.3.0 Check for brand image assets (automatic)
Before generating any images, check if the user provided brand image / IP assets in the global settings:
- Look for
global.brandImages in the draft data (or files in __drafts/brand-images/).
- If brand images exist, use
visual_understanding to analyze each image — extract the IP character, color palette, art style, and key visual elements.
- When generating illustrations, card decorations, or any post imagery:
- Incorporate the brand IP character or elements where contextually appropriate (e.g., as mascot illustrations, corner decorations, section dividers).
- Match the brand's color palette and art style to maintain visual consistency.
- Reference the brand image explicitly in
generate_image prompts (e.g., "in the style of the brand mascot", include description of the character/element).
- For
wechat-official-accounts cover images, make a case-by-case decision on whether to incorporate brand elements. Use them when they strengthen recognition, trust, or thematic fit; skip them when they would reduce clarity, editorial quality, or topic accuracy.
- If no brand images exist, proceed normally without this constraint.
This step ensures all generated visuals feel cohesive with the user's established brand identity.
4.3.1 Check outline image materials for reference-based recreation (automatic)
When articles[].outline[].materials or articles[].materials includes screenshots, charts, UI captures, product images, diagrams, or other content-relevant images, do not treat them as passive attachments.
For each image material:
- Use
visual_understanding to identify what the image shows, what information matters, and which outline node or card it should support.
- If the image is useful for the final content, prefer a new generated asset instead of placing the raw screenshot directly into a card.
- Call
generate_images with the source image in reference_images. The prompt should preserve the source image's important information while adapting it to the resolved preset/style.
- Add visual emphasis where it helps comprehension: highlighted key areas, zoom callouts, arrows, labels, comparison boxes, focus rings, cropped detail panels, or before/after framing.
- Save the generated result under
posts/<post_id>/assets/ and use that generated asset in the card or article HTML.
- Keep node scope: an image attached to one outline node should primarily influence that node/card. Expand it to other cards only when the image clearly supports the broader narrative.
Raw image materials may still be used as factual references, but card-facing visuals should be recreated or annotated when that makes the message clearer.
4.3.2 Handle missing images with generation or placeholders (automatic)
When a card or article section needs an image but the user did not provide one, first decide whether image generation is appropriate.
Generate an image when the needed visual is:
- a conceptual cover, atmosphere image, section opener, trend, emotion, vision, or abstract topic visual
- a diagram-like illustration, analogy, workflow, comparison, pain-point scene, before/after change, or methodology explanation
- a brand/IP extension based on provided brand assets or style requirements
- a card-level visual enhancement that improves attention, hierarchy, or memorability
- not dependent on exact real people, exact real events, strict evidence, or precise source data
Do not generate an image when the needed visual must be strictly factual or would be misleading if invented:
- data charts, financial reports, product dashboards, experiment results, legal/medical/financial evidence
- exact real people, real brand/product UI details, news scenes, accident scenes, user reviews, chat logs
- local explanations that require an original screenshot or source image that the user did not provide
- article transitions where a styled placeholder or information layout communicates better than an illustration
If generation is appropriate, call generate_images after style is resolved and save the result under posts/<post_id>/assets/. If generation is not appropriate, create a styled placeholder instead:
- Card placeholders should match the preset: dashed frame, icon block, muted panel, label chip, decorative grid, or "pending screenshot/data chart" module.
- WeChat article placeholders should use a clear placeholder line such as
【Image placeholder: purpose or scene description】.
- For missing screenshots or data charts, label them as pending replacement assets. Do not fabricate evidence-like visuals.
For every image the cards need:
- Derive the visual brief from the resolved style (preset palette / user artifact / platform default).
- Pick the tool that best preserves the style:
generate_image — preferred when the preset or user artifact implies a specific illustrative language. Pass the style cues explicitly in the prompt (color tokens, mood words, composition, negative prompts for styles to avoid).
image_search — acceptable for neutral, topic-driven photography or real-world references. Use batch mode (one call, multiple requirements). Before accepting any returned image, verify with visual_understanding that its colors, lighting, and composition do not fight the style; discard mismatches rather than force-fit.
visual_understanding — also used to read the dimensions / content of any user-supplied reference image before placing it into a card.
- Save the files:
- Card-local →
posts/<post_id>/assets/<name>.<ext>.
- Cross-post →
shared/<name>.<ext>.
4.4 Write the content
Load Human Writing Style before drafting card copy or article prose. This reference is the internal source of truth for human texture, author voice, anti-generic-copy checks, and platform-specific writing self-checks.
4.4.0 Build the human-writing brief
Before authoring HTML, write a short internal brief from the available context:
- author voice: who is speaking and why the reader should trust this voice
- target reader: the concrete reader state, pain, desire, or decision moment
- reader action: save, comment, follow, consult, compare, try, buy, or remember a viewpoint
- evidence: uploaded references, product details, screenshots, comparisons, cases, constraints, or observed scenes
Infer from global.author, global.brandPosition, global.targetAudience, optional __brand/brand-config.json, articles[].style, articles[].notes, title, outline, and uploaded materials. Ask only when the missing answer changes the direction of the post and no brand config fallback can answer it. Do not invent first-person experience, customer proof, metrics, or quotes to create human texture.
4.4.1 Author the platform content
For rednote / instagram: use write_file to author each card HTML at the exact path declared in cards. Match the resolved style:
- Preset chosen → link the copied CSS/JS from
../../../shared/presets/<preset>/, follow its class naming conventions, reuse its tokens.
- User artifact → reproduce layout, colors, typography, and component treatments faithfully.
- No preset and no artifact → follow the Platform Defaults and the constraints in references/card-html-constraints.md.
Reference only local image files saved in 4.3. Load Card HTML Constraints for the full technical rules, content density requirements, and minimal HTML skeleton before writing any card.
For wechat-official-accounts: use write_file to author the article HTML at the path declared in `post.jso
…(truncated)
1---2name: self-media-composer3description: Use when the user wants to create, extend, or edit self-media posts or card/article projects for Rednote/Xiaohongshu, Instagram, WeChat Official Accounts, or similar platforms. Trigger on [@self_media_project:...], create/add post, make cards, generate social cards, write WeChat article, multilingual self-media requests, Rednote tags, WeChat article, Instagram cards, social media cards, content project. Also use for self-media post-publication operations such as immediate sync, real data refresh, published-data import, post-publication data sync, operations review dashboards, article ops review, and fixed `ops/*` data updates.4---5
6# Self-Media Composer Skill
7
8Complete capability for building and managing self-media projects. One project groups many posts; each post is an independent folder with its own meta and card sequence. This skill scaffolds that structure, authors the cards, generates reference engagement data, and keeps the root index in sync.
9
10---
11
12## When to Load This Skill
13
14Load this skill **immediately and before any other action** when the user's message matches any of the following patterns.
15
16### English
17
18| User says | Load reason |
19| --- | --- |
20| "create a post" / "add a post" | New post creation |
21| "make cards for Rednote / Instagram" | Card-based post authoring |
22| "write a WeChat article" / "WeChat official account post" | Article post authoring |
23| "build a self-media project" / "start a content project" | Project scaffolding |
24| "generate social cards" / "design card images" | Card design |
25| "create content for [platform]" | Any platform post |
26| "post-publication review" / "article ops review" | Operations data sync |
27| "fetch published data" / "update ops files" | Operations data sync |
28| "sync now" / "real data refresh" | Operations data sync |
29| Contains `[@self_media_project:...]` | Existing project reference |
30
31### Multilingual
32
33Load for equivalent requests in any user language, including Chinese-language requests for Xiaohongshu/Rednote posts, WeChat Official Account articles, Instagram cards, card-based social posts, content projects, publishing-data import, immediate sync, real data refresh, operations review, or any message containing `[@self_media_project:...]`.
34
35> **Note:** When localized platform aliases appear, treat them as the corresponding platform values. See Platform Aliases in the Platform Defaults section.
36
37---
38
39## Execution
40
41All Python snippets in this document must run through `run_sdk_snippet`:
42
43```python
44run_sdk_snippet(
45 python_code="""
46from sdk.tool import tool
47result = tool.call('create_self_media_project', {
48 'project_path': 'ai-monthly',
49 'platform': 'rednote'
50})
51print(result)
52"""
53)
54```
55
56`result` exposes `result.ok`, `result.content`, `result.data`. Access structured data via `result.data`; the object is not subscriptable.
57
58---
59
60## Output Language Contract
61
62The skill documentation is written in English, but generated content must adapt to the user's language.
63
641. Infer the user's preferred output language from the current user message first, then from active draft content, existing post language, project context, and explicit platform requirements. If the target language is still ambiguous and the choice affects the final content, ask one concise clarification.
652. Write all user-facing text in the inferred language: questions, option labels, project/post display names, titles, subtitles, card copy, article prose, captions, comments, CTA text, placeholder labels, relative time strings, operations review prose, and template descriptions.
663. Keep machine contracts stable: platform values, preset IDs, JSON keys, enum values, CSS class names, JS namespaces, file extensions, and API/tool parameters stay in their documented form.
674. Use safe filesystem IDs. Prefer lowercase ASCII slugs for `project_path`, `post_id`, card filenames, and preset names unless the user explicitly needs localized filenames and the path is safe.
685. Do not translate brand names, platform names, product names, source quotes, code identifiers, or fixed schema values. Translate surrounding explanation and content intent.
696. For Rednote tags, choose tags that fit the user's output language and the platform's search behavior. The Chinese hashtag library is a reference set for Chinese/Xiaohongshu SEO, not a command to force Chinese tags in non-Chinese output.
707. Set HTML `lang` attributes to the inferred language when writing cards or articles (`zh-CN`, `en`, `ja`, etc.).
71
72---
73
74## Project Concept
75
76A self-media project is a Magic Project folder whose `magic.project.js` declares `type: "self-media"`. It contains:
77
78- `magic.project.js` at the root — JSONP, holds a per-platform posts index
79- `posts/<post-id>/` — one folder per post, fully self-contained
80- `shared/` — optional, assets shared across posts (including copied preset bundles)
81
82Directory layout:
83
84```
85<project-root>/
86├── magic.project.js
87├── posts/
88│ ├── <post-id>/
89│ │ ├── post.json
90│ │ ├── cards/ # rednote / instagram only
91│ │ │ ├── <card>.html
92│ │ │ └── ...
93│ │ └── assets/
94│ ├── <wechat-post-id>/ # wechat-official-accounts
95│ │ ├── post.json
96│ │ ├── <article>.html # single article HTML
97│ │ └── assets/
98│ │ ├── cover-hero.jpg
99│ │ └── cover-square.jpg
100│ └── ...
101└── shared/
102 └── presets/
103 └── <preset-name>/
104 ├── <preset-name>.css
105 └── <preset-name>.js
106```
107
108Preset source files (inside this skill) are organized by platform:
109
110```
111presets/
112├── rednote/
113│ ├── neo-brutalism/
114│ ├── code-dispatch/
115│ ├── dark-tech/
116│ ├── gradient-editorial/
117│ ├── personal-insight/
118│ ├── film-vintage/
119│ ├── warm-journal/
120│ ├── paper-column/
121│ ├── signal-grid/
122│ └── product-launch-preset/
123├── instagram/
124│ ├── ins-modern/
125│ ├── ins-minimal/
126│ ├── ins-dark/
127│ ├── ins-retro/
128│ ├── ins-fluent-depth/
129│ ├── ins-token-system/
130│ ├── ins-creator-studio/
131│ ├── ins-film-frame/
132│ ├── ins-warm-journal/
133│ └── ins-signal-grid/
134└── wechat-official-accounts/
135 └── (coming soon)
136```
137
138> For `magic.project.js` and `post.json` format examples, path rules, and file authoring rules, see [references/file-formats.md](./references/file-formats.md).
139
140### File authoring rules (summary)
141
142- `magic.project.js` must be generated by `create_self_media_project`. Never create or overwrite it with `write_file`. Edit its inner `posts` array via `edit_file` only.
143- `post.json` is produced by `create_self_media_post`. Edit it with `edit_file` for subsequent changes.
144- Card HTML files can be authored directly with `write_file`.
145
146---
147
148## Platform Defaults
149
150Currently supported `platform` values: `rednote`, `instagram`, `wechat-official-accounts`.
151
152### Platform Aliases
153
154| User says | Maps to platform |
155| ---------------------------------- | -------------------------- |
156| 微信公众号 / 公众号 / 微信公众账号 | `wechat-official-accounts` |
157| 小红书 / 红书 / RED | `rednote` |
158| ins / Instagram | `instagram` |
159
160When the user mentions any localized alias above, treat it as the corresponding platform value without asking for clarification. Keep the canonical platform values in files and tool calls.
161
162The table below is a fallback only. When the user explicitly specifies card size or aspect ratio, follow the user's values; do not override them with the defaults.
163
164| platform | Default size | Aspect | Notes |
165| --- | --- | --- | --- |
166| `rednote` | 540x720 | 3:4 | Xiaohongshu vertical card, standard feed |
167| `instagram` | 540x675 | 4:5 | Instagram feed portrait |
168| `wechat-official-accounts` | N/A | N/A | Article post: single HTML + heroCover + thumbnailCover |
169
170Fallback rules inside `instagram`: if the user wants a square layout, use `540x540` (1:1); for stories or reels covers, use `540x960` (9:16). Ask before assuming.
171
172Decision order every time you pick a card canvas size:
173
1741. If the user specified a size or aspect ratio in the current session, use it.
1752. Else, if the user specified only a platform, use the platform default from the table above.
1763. Else, ask the user which platform and size they want before starting.
177
178---
179
180## Built-in Presets
181
182Presets are organized by platform under `presets/<platform>/<preset>/`. Each preset is a pair of files (`<preset>.css` + `<preset>.js`).
183
184| Platform | Preset | Style summary |
185| --- | --- | --- |
186| `rednote` | `neo-brutalism` | Neo-Brutalism: thick black borders, hard offset shadows, saturated palette. |
187| `rednote` | `code-dispatch` | Code Dispatch: high-contrast editorial style, black/white/red palette, monospace labels, no rounded corners, grid background texture. Best for tech/coding/AI topics. |
188| `rednote` | `dark-tech` | Dark-Tech: deep black background, gold accent, thin 1px borders, heavy/light font-weight contrast. Inspired by DJI-style review cards. Best for product/gear reviews. |
189| `rednote` | `gradient-editorial` | Image Editorial: cover uses hero/theme image with gradient overlay for text readability, clean white content pages, rounded cards. Best for AI/tech insight articles. |
190| `rednote` | `personal-insight` | Personal Insight: clean white background, profile avatar, numbered sections, reading-note style. Best for personal reflections and knowledge sharing. |
191| `rednote` | `film-vintage` | Film Vintage: dark cinematic cover, polaroid-style photo frames, mono grain texture, red accent, serif+mono typography. Best for film photography, gear reviews, and city walk journals. |
192| `rednote` | `warm-journal` | Warm Journal: photo-led journal pages, handwritten titles, khaki/beige paper textures, scattered notes, and polaroid frames. Best for lifestyle, product notes, and city records. |
193| `rednote` | `paper-column` | Paper Column: paper texture, serif display titles, marginal notes, pull quotes, ledgers, and evidence frames. Best for essays, analysis, knowledge columns, and field-note narratives. |
194| `rednote` | `signal-grid` | Signal Grid: strict grid rhythm, light display type, one accent color, matrix rows, KPI blocks, and ranking bars. Best for product notes, comparisons, launch explainers, and structured decisions. |
195| `rednote` | `product-launch-preset` | Product Launch: white background, 6px red top accent bar, black text + red highlights only, sharp 2px badges, 10px rounded image containers. Best for product feature announcements and release notes. |
196| `instagram` | `ins-modern` | Instagram Modern: bold white editorial cards, crisp black structure, hard shadows, and selective social accents. Best for creator productivity and punchy carousel hooks. |
197| `instagram` | `ins-minimal` | Instagram Minimal: quiet premium whitespace, fine rules, serif display type, and calm editorial hierarchy. Best for digests, summaries, and point-of-view posts. |
198| `instagram` | `ins-dark` | Instagram Dark Tech: dark product-launch energy, electric accents, console-like modules, and high-contrast data blocks. Best for tools, productivity, and technical topics. |
199| `instagram` | `ins-retro` | Instagram Retro Story: warm paper, stamp details, ornamental rules, and story-first pacing. Best for storytelling content and visual guides. |
200| `instagram` | `ins-fluent-depth` | Instagram Fluent Depth: soft layered surfaces, restrained depth, calm material feel, and readable product storytelling. Best for workflow explainers and high-trust product stories. |
201| `instagram` | `ins-token-system` | Instagram Token System: neutral surfaces, semantic color roles, compact lozenges, and enterprise grid rhythm. Best for structured decisions and product comparisons. |
202| `instagram` | `ins-creator-studio` | Instagram Creator Studio: profile-led structure, numbered lessons, credibility blocks, and personal voice cues. Best for personal insights and creator education. |
203| `instagram` | `ins-film-frame` | Instagram Film Frame: cinematic black frame, contact-sheet rhythm, warm highlights, and review-ready panels. Best for photography, gear reviews, and city walk journals. |
204| `instagram` | `ins-warm-journal` | Instagram Warm Journal: soft journal pages, taped-note modules, warm accents, and lifestyle-friendly grids. Best for lifestyle notes, product diaries, and cozy recommendations. |
205| `instagram` | `ins-signal-grid` | Instagram Signal Grid: strict grid rhythm, matrix rows, KPI cells, and decision-oriented comparison blocks. Best for product comparisons, launch explainers, and structured decisions. |
206| `wechat-official-accounts` | _(coming soon)_ | Presets for WeChat article style will be added here. |
207
208Source paths inside this skill:
209
210```
211presets/rednote/neo-brutalism/neo-brutalism.{css,js}
212presets/rednote/code-dispatch/code-dispatch.{css,js}
213presets/rednote/dark-tech/dark-tech.{css,js}
214presets/rednote/gradient-editorial/gradient-editorial.{css,js}
215presets/rednote/personal-insight/personal-insight.{css,js}
216presets/rednote/film-vintage/film-vintage.{css,js}
217presets/rednote/warm-journal/warm-journal.{css,js}
218presets/rednote/paper-column/paper-column.{css,js}
219presets/rednote/signal-grid/signal-grid.{css,js}
220presets/rednote/product-launch-preset/product-launch.{css,js}
221presets/instagram/ins-modern/ins-modern.{css,js}
222presets/instagram/ins-minimal/ins-minimal.{css,js}
223presets/instagram/ins-dark/ins-dark.{css,js}
224presets/instagram/ins-retro/ins-retro.{css,js}
225presets/instagram/ins-fluent-depth/ins-fluent-depth.{css,js}
226presets/instagram/ins-token-system/ins-token-system.{css,js}
227presets/instagram/ins-creator-studio/ins-creator-studio.{css,js}
228presets/instagram/ins-film-frame/ins-film-frame.{css,js}
229presets/instagram/ins-warm-journal/ins-warm-journal.{css,js}
230presets/instagram/ins-signal-grid/ins-signal-grid.{css,js}
231```
232
233When the user picks a preset (see Workflow Step 4.1), read the source files from `presets/<platform>/<preset>/` and copy both files once into the project at `shared/presets/<preset>/`. Reference them from every card with `<link>` and `<script>` tags using `../../../shared/presets/<preset>/<preset>.css|.js`.
234
235### Custom Preset Generation (Optional Sub-Skill)
236
237When the user wants a visual style that is not covered by any built-in preset, a custom preset can be generated from a free-form description. This capability is encapsulated in the **`generate-preset`** sub-skill:
238
239```
240generate-preset/SKILL.md (inside this skill folder)
241```
242
243**Load this sub-skill when:**
244
245- The user selects "Custom style" in the Step 4.1 picker.
246- The user explicitly asks to "create a new preset", "design a theme", or "generate a style".
247- The user provides a reference image / Figma frame and asks for a matching preset.
248
249**What it produces:** a `<preset-name>.css` + `<preset-name>.js` pair, saved to `<project-root>/shared/presets/<preset-name>/`, ready to be linked from cards exactly like a built-in preset.
250
251---
252
253## Core Tools
254
255### create_self_media_project
256
257Scaffolds a new self-media project. Creates the project folder, `posts/`, `shared/`, and a valid `magic.project.js`. It does not generate any frontend loader HTML - rendering lives in other frontends.
258
259| Parameter | Required | Description |
260| --- | --- | --- |
261| `project_path` | Yes | Project folder path, workspace-relative. Reflect the topic; prefer a safe ASCII slug unless the user explicitly needs a localized filesystem name. |
262| `platform` | Yes | One of `rednote`, `instagram`, `wechat-official-accounts`. |
263| `posts` | No | Optional pre-registered post index entries. Each item `{ "id": "...", "name": "..." }`. Default `[]`. |
264
265Returns: `{ project_path, project_name, platform, posts_count }`.
266
267### create_self_media_post
268
269Creates a single post directory (`posts/<post_id>/`) with `post.json` and an empty `assets/`. For card-based platforms (rednote / instagram) also creates an empty `cards/`. Optionally registers the post in the root `magic.project.js` posts array of the project's platform.
270
271| Parameter | Required | Description |
272| --- | --- | --- |
273| `project_path` | Yes | Self-media project root, workspace-relative. |
274| `post_id` | Yes | Stable id, safe for filesystem (for example `ai-bill`). Used as folder name and `post.json.id`. |
275| `post_name` | Yes | Display name written into the root `posts[]` entry and as the fallback `meta.title`. |
276| `meta` | No | Object merged into `post.json.meta`. Free-form fields: `title`, `subtitle`, `tags`, `author`, `feedTitle`, `feedLikes`, `commentCount`, `comments`, `time` (wechat), `interactionReference`, etc. For `rednote`, `tags` should use the structured hashtag pyramid unless the user supplied a legacy string/array format. |
277| `cards` | No | **rednote / instagram only.** Initial value for `post.json.cards`. Paths relative to the post folder, for example `"cards/01.html"`. |
278| `article` | No | **wechat-official-accounts only.** Relative path to the single HTML article file, for example `"my-article.html"`. When provided, the post is treated as a WeChat article post; `cards` is ignored. |
279| `hero_cover` | No | **wechat-official-accounts only.** Relative path to the hero cover image (21:9), for example `"assets/cover-hero.jpg"`. Written as `heroCover` in `post.json`. |
280| `thumbnail_cover` | No | **wechat-official-accounts only.** Relative path to the square thumbnail cover image, for example `"assets/cover-square.jpg"`. Written as `thumbnailCover` in `post.json`. |
281| `register_in_project` | No | Default `true`. Append/update the entry in the root `magic.project.js` posts array. If the frontend prompt says the post is already pre-registered, explicitly pass `false` and do not edit the root index. |
282
283Idempotence: if `posts/<post_id>/` already exists, the tool merges `meta` (shallow merge, new keys win), keeps existing `cards` / `article` / `heroCover` / `thumbnailCover` untouched unless the caller passes new values, and preserves the root posts entry order.
284
285Returns: `{ post_path, post_json_path, registered }`.
286
287---
288
289## Workflow
290
291Follow this loop until the user's intent is fully served.
292
293### Step 0 - check for existing planning data (automatic)
294
295Before asking any questions, check if the project already contains user planning data from the frontend:
296
2971. Look for `__drafts/draft.json` in the self-media folder.
2982. If found, `read_files` to load it. See [Drafts & Templates Format](./references/drafts-format.md) for the schema.
2993. If `__drafts/reference-index.json` exists, read it immediately after `draft.json`. Treat it as the unified reference entry point.
3004. If brand context is needed and `draft.json.global` is missing, sparse, or stale, try to read `__brand/brand-config.json` before asking the user. Treat it as an optional fallback. Current-session user instructions and explicit `draft.json.global` values outrank it.
3015. Extract and apply context:
302 - `global.author` / `global.brandPosition` / `global.targetAudience` → brand context (no need to ask)
303 - `global.brandImages` → brand IP image assets for image generation reference (use in Step 4.3)
304 - `__brand/brand-config.json` fields → brand context fallback when `global` fields are unavailable
305 - `articles[].title` / `articles[].outline` → content structure is pre-planned
306 - `articles[].visualPreset` → visual preset is pre-selected (skip Step 4.1 for that article)
307 - `articles[].style` → content tone is chosen
308 - `articles[].platform` → known platform for that article
309 - `articles[].materials` → article-level reference files available via `relativePath`
310 - `articles[].outline[].materials` → node-scoped reference files available via `relativePath`
311 - `articles[].visualReferenceFiles` → visual-style references available via `file_path` or inline `content`
312 - `articles[].notes` → explicit user instructions to follow
313 - `articles[].cardCount` → target card count
3146. Read and understand all uploaded references before drafting, designing, or generating images. This rule applies regardless of where the user attached the file in the frontend.
3157. If the draft provides enough information to proceed (at least one article with title plus either platform or clear continuation context), skip directly to the appropriate step. If the draft is incomplete, proceed from Step 1 but pre-fill known fields.
316
317> This step is silent — do not announce "I found a draft" unless the data is ambiguous and needs user confirmation.
318
319### Step 0.1 - read uploaded references before creation
320
321This step is mandatory whenever uploaded references exist.
322
3231. Resolve references from `reference-index.json` first.
3242. If `reference-index.json` is missing or incomplete, fall back to:
325 - `__brand/brand-config.json`, when brand context is needed
326 - `global.brandImages`
327 - `articles[].materials`
328 - `articles[].outline[].materials`
329 - `articles[].visualReferenceFiles`
3303. Resolve each reference in this order:
331 - `relativePath`
332 - `file_path` / `file_id`
333 - inline `content`
3344. Read and understand the reference before drafting copy, generating images, or designing cards.
3355. Group the references by role:
336 - `brand`
337 - `article-material`
338 - `outline-material`
339 - `visual-reference`
3406. Apply them at the correct scope. Outline-node references should influence the matching node first, not the whole post by default.
3417. If a reference cannot be fully read, do not ignore it. State the limitation explicitly and still use its name, description, path, and surrounding context.
342
343### Step 1 - understand intent and platform
344
345- Clarify the topic and target platform. If platform or content type is missing, ask one question before proceeding.
346- For `wechat-official-accounts`: the post is a single long-form HTML article plus two cover images — not a card sequence.
347- For `rednote` / `instagram`: the post is a sequence of fixed-size card HTML files.
348- Outline how many posts the request implies, and for each post the rough number of cards (or confirm it is a single article for WeChat).
349
350### Step 2 - research factual content (when needed)
351
352- Use `web_search` and `read_webpages_as_markdown` to gather up-to-date facts, data points, quotes, or source material for the copy.
353- Always incorporate the uploaded references from Step 0.1 before expanding with external research. Uploaded references outrank generic web research when they cover the same topic.
354- **Do not** search or generate images in this step. Images must serve the visual language, and the visual language is only fixed in Step 4.1. Collecting or generating images before the style is resolved will force the cards to accommodate mismatched visuals instead of the other way around.
355
356### Step 3 - scaffold the project (first time only)
357
358- Call `create_self_media_project` with `project_path` and `platform`.
359- Optionally pass `posts=[{id, name}, ...]` if you already know the full post list.
360
361### Step 4 - author each post
362
363For every post, run this ordered sub-flow. Do not skip or reorder steps.
364
365Before running 4.1-4.5 for a post, confirm that you have already read and understood:
366
367- article-level materials for that post
368- outline-node materials for that post
369- visual reference files for that post
370- any brand image assets that influence stylistic or brand consistency
371
372**4.1 Ask the user which preset to use (mandatory for all platforms)**
373
374Before creating any post content, call `ask_user` exactly once and let the user pick the visual template. Render the question and option labels in the user's preferred output language while keeping the canonical preset IDs unchanged. Present only the presets available for the current platform, plus an explicit "No template" option:
375
376**For `rednote`:**
377
378```xml
379<question type="select">
380Please choose a visual template for the cards:
381<option>neo-brutalism — thick black borders, hard offset shadows, saturated palette</option>
382<option>code-dispatch — high-contrast editorial, black/white/red, monospace labels, grid texture; ideal for tech/coding/AI topics</option>
383<option>dark-tech — deep black background, gold accent, thin borders, DJI-style; ideal for product/gear reviews</option>
384<option>gradient-editorial — hero image with gradient overlay, clean white content pages, modern editorial style; ideal for AI/tech insight articles</option>
385<option>personal-insight — clean white background, profile avatar, numbered sections; ideal for personal reflections and knowledge sharing</option>
386<option>film-vintage — cinematic cover, polaroid photo frames, grain texture, red accent; ideal for photography, gear reviews, and city walks</option>
387<option>warm-journal — photo-led journal pages, handwritten titles, khaki/beige paper textures; ideal for lifestyle, product notes, and city records</option>
388<option>paper-column — paper texture, serif titles, marginal notes, pull quotes, and ledgers; ideal for essays, analysis, and knowledge columns</option>
389<option>signal-grid — strict grid rhythm, one accent color, KPI blocks, matrix rows, and ranking bars; ideal for comparisons, product notes, and decisions</option>
390<option>product-launch-preset — white background, red top accent bar, sharp badges, minimal dual-color; ideal for product feature announcements and release notes</option>
391<option>Custom style — describe the visual language you want and a preset will be generated for you</option>
392<option>No template — design freely following the platform baseline</option>
393</question>
394```
395
396**For `instagram`:**
397
398```xml
399<question type="select">
400Please choose a visual template for the cards:
401<option>ins-modern — white background, generous whitespace, minimal typography</option>
402<option>ins-minimal — restrained whitespace, fine dividers, minimal hierarchy; ideal for digests and summary posts</option>
403<option>ins-dark — dark tech styling, neon accents, high-contrast modules; ideal for tools, productivity, and technical topics</option>
404<option>ins-retro — retro headlines, warm paper tones, ornamental marks; ideal for storytelling and visual guides</option>
405<option>ins-fluent-depth — soft layered surfaces, restrained depth, calm product storytelling; ideal for workflow explainers and product stories</option>
406<option>ins-token-system — neutral surfaces, semantic color roles, compact lozenges, enterprise grid rhythm; ideal for product comparisons and structured decisions</option>
407<option>ins-creator-studio — profile-led lessons, credibility blocks, personal voice cues; ideal for creator education and reflections</option>
408<option>ins-film-frame — cinematic frame, contact-sheet rhythm, warm highlights; ideal for photography, gear reviews, and city walks</option>
409<option>ins-warm-journal — soft journal pages, taped-note modules, warm lifestyle grids; ideal for product notes and cozy recommendations</option>
410<option>ins-signal-grid — strict grid rhythm, KPI cells, matrix rows; ideal for comparisons, launch explainers, and decisions</option>
411<option>Custom style — describe the visual language you want and a preset will be generated for you</option>
412<option>No template — design freely following the platform baseline</option>
413</question>
414```
415
416**For `wechat-official-accounts`:**
417
418```xml
419<question type="select">
420Please choose a visual template for the article:
421<option>Custom style — describe the visual language you want and a preset will be generated for you</option>
422<option>No template — design freely following the WeChat article baseline (presets coming soon)</option>
423</question>
424```
425
426Rules:
427
428- Do **not** skip this prompt for any platform — even when the user already described a style vaguely, the preset choice must be explicit.
429- If the user picks a **built-in preset**, read the source files from `presets/<platform>/<preset>/` inside this skill and copy them into the project once:
430 - source: `presets/<platform>/<preset>/<preset>.css` and `presets/<platform>/<preset>/<preset>.js`.
431 - destination: `<project-root>/shared/presets/<preset>/<preset>.css` and `<preset>.js`.
432 - Use `read_files` to load the sources and `write_file` to copy; skip the copy if the destination already exists.
433- If the user picks **Custom style**, ask a follow-up free-text question:
434 ```xml
435 <question type="text">
436 Describe the visual style you want (e.g. mood, colors, font feel, decoration, content domain):
437 </question>
438 ```
439 Then load and follow the **`generate-preset` sub-skill** (`generate-preset/SKILL.md` inside this skill folder) to generate a custom CSS + JS preset bundle. Save the generated files to `<project-root>/shared/presets/<preset-name>/` before proceeding to Step 4.2. Treat the generated preset exactly like a built-in preset for all subsequent card authoring steps.
440- If the user picks **No template**, go straight to 4.2 without copying anything; content will be authored against the plain platform defaults.
441- When the user explicitly provides their own HTML template, screenshot, Figma link, or CSS spec in this session, that artifact outranks the preset choice. You may still copy a preset in parallel for icon/helper utilities, but layout and colors must follow the user artifact.
442
443**4.2 Create the post folder**
444
445Before calling `create_self_media_post`, generate a complete `meta` object from the planned article/card content. Besides title, subtitle, tags, author, and feed title, every new post must include reference engagement data:
446
447- `feedLikes`: a platform-appropriate display string, such as `"1.8w"`, `"12.3k"`, or `"860"`.
448- `commentCount`: a display string aligned with `feedLikes` and the likely engagement level.
449- `comments`: 3-5 plausible sample evaluations for every generated post, written in the audience's voice and tied to the actual content. Rednote / Instagram previewers render them; WeChat stores them as a reference evaluation pool. Do not use generic praise such as "Great post".
450- `time`: for `wechat-official-accounts`, a natural relative feed time in the user's output language, such as `"4 minutes ago"` or the localized equivalent.
451- `interactionReference`: optional but recommended. Use it for non-rendered notes such as `{ "level": "medium-high", "basis": "product launch / strong pain point", "disclaimer": "reference display data, not real platform analytics" }`.
452
453Treat these numbers and evaluations as reference/display data, not verified analytics. They should feel credible for the platform, topic, audience size, and content intensity; do not invent factual performance claims such as "real launch data" unless the user supplied the data.
454
455**4.2.1 Build `meta.tags` for `rednote`**
456
457For every `rednote` post, load [Rednote Hashtag Library](./references/hashtag-library.md) before calling `create_self_media_post`. Populate `meta.tags` with the four-layer pyramid:
458
459```json
460{
461 "core": ["workwear"],
462 "mid": ["commute outfits", "petite styling"],
463 "longtail": ["outfits for new office workers", "155cm styling tips"],
464 "trend": ["dopamine dressing"]
465}
466```
467
468Rules:
469
4701. Total count must be 5-8 tags. Hard cap: 10.
4712. Output order is `core -> mid -> longtail -> trend`.
4723. `core`: 1-2 category anchors.
4734. `mid`: 2-3 scenario, style, or search-intent tags.
4745. `longtail`: 2-3 audience, pain-point, location, body-type, budget, or use-case tags.
4756. `trend`: 0-1 current trend or official activity tag. Omit stale trend tags.
4767. Travel posts must include a concrete city, area, route, or attraction tag.
4778. If the user supplies tags as a string or array, preserve them only when they are relevant and within the cap; otherwise normalize them into the four fields and remove off-topic tags.
4789. If the topic is outside the built-in categories, build the same four layers from the post's audience, scenario, pain point, and trend. Do not force a mismatched category from the library.
479
480🔴 CHECKPOINT · Rednote tag confirmation:
481
482- If the user did not provide tags, propose the final 5-8 tags once before creating the post.
483- If a draft or frontend planning payload already contains tag intent, use it as the source of truth and do not ask again unless the tags violate the cap, contain irrelevant traffic-bait, or miss a required concrete qualifier such as a travel location.
484
485**For `rednote` / `instagram`:** call `create_self_media_post` with `post_id`, `post_name`, the complete `meta`, and the planned `cards` list. This yields `posts/<id>/post.json`, `cards/`, and `assets/`. If the frontend prompt states that the post was pre-registered in `magic.project.js`, pass `register_in_project=false`.
486
487**For `wechat-official-accounts`:** call `create_self_media_post` with `post_id`, `post_name`, the complete `meta`, `article` (the filename), `hero_cover` (e.g. `"assets/cover-hero.jpg"`), and `thumbnail_cover` (e.g. `"assets/cover-square.jpg"`). This yields `posts/<id>/post.json` and `assets/`. No `cards/` folder is created. If the frontend prompt states that the post was pre-registered in `magic.project.js`, pass `register_in_project=false`.
488
489**4.3 Collect or generate images (after the style is fixed)**
490
491Only after the preset decision in 4.1 is done are images allowed to enter the pipeline. Images serve the style; never let images dictate it.
492
493**4.3.0 Check for brand image assets (automatic)**
494
495Before generating any images, check if the user provided brand image / IP assets in the global settings:
496
4971. Look for `global.brandImages` in the draft data (or files in `__drafts/brand-images/`).
4982. If brand images exist, use `visual_understanding` to analyze each image — extract the IP character, color palette, art style, and key visual elements.
4993. When generating illustrations, card decorations, or any post imagery:
500 - Incorporate the brand IP character or elements where contextually appropriate (e.g., as mascot illustrations, corner decorations, section dividers).
501 - Match the brand's color palette and art style to maintain visual consistency.
502 - Reference the brand image explicitly in `generate_image` prompts (e.g., "in the style of the brand mascot", include description of the character/element).
503 - For `wechat-official-accounts` cover images, make a case-by-case decision on whether to incorporate brand elements. Use them when they strengthen recognition, trust, or thematic fit; skip them when they would reduce clarity, editorial quality, or topic accuracy.
5044. If no brand images exist, proceed normally without this constraint.
505
506> This step ensures all generated visuals feel cohesive with the user's established brand identity.
507
508**4.3.1 Check outline image materials for reference-based recreation (automatic)**
509
510When `articles[].outline[].materials` or `articles[].materials` includes screenshots, charts, UI captures, product images, diagrams, or other content-relevant images, do not treat them as passive attachments.
511
512For each image material:
513
5141. Use `visual_understanding` to identify what the image shows, what information matters, and which outline node or card it should support.
5152. If the image is useful for the final content, prefer a new generated asset instead of placing the raw screenshot directly into a card.
5163. Call `generate_images` with the source image in `reference_images`. The prompt should preserve the source image's important information while adapting it to the resolved preset/style.
5174. Add visual emphasis where it helps comprehension: highlighted key areas, zoom callouts, arrows, labels, comparison boxes, focus rings, cropped detail panels, or before/after framing.
5185. Save the generated result under `posts/<post_id>/assets/` and use that generated asset in the card or article HTML.
5196. Keep node scope: an image attached to one outline node should primarily influence that node/card. Expand it to other cards only when the image clearly supports the broader narrative.
520
521Raw image materials may still be used as factual references, but card-facing visuals should be recreated or annotated when that makes the message clearer.
522
523**4.3.2 Handle missing images with generation or placeholders (automatic)**
524
525When a card or article section needs an image but the user did not provide one, first decide whether image generation is appropriate.
526
527Generate an image when the needed visual is:
528
529- a conceptual cover, atmosphere image, section opener, trend, emotion, vision, or abstract topic visual
530- a diagram-like illustration, analogy, workflow, comparison, pain-point scene, before/after change, or methodology explanation
531- a brand/IP extension based on provided brand assets or style requirements
532- a card-level visual enhancement that improves attention, hierarchy, or memorability
533- not dependent on exact real people, exact real events, strict evidence, or precise source data
534
535Do not generate an image when the needed visual must be strictly factual or would be misleading if invented:
536
537- data charts, financial reports, product dashboards, experiment results, legal/medical/financial evidence
538- exact real people, real brand/product UI details, news scenes, accident scenes, user reviews, chat logs
539- local explanations that require an original screenshot or source image that the user did not provide
540- article transitions where a styled placeholder or information layout communicates better than an illustration
541
542If generation is appropriate, call `generate_images` after style is resolved and save the result under `posts/<post_id>/assets/`. If generation is not appropriate, create a styled placeholder instead:
543
544- Card placeholders should match the preset: dashed frame, icon block, muted panel, label chip, decorative grid, or "pending screenshot/data chart" module.
545- WeChat article placeholders should use a clear placeholder line such as `【Image placeholder: purpose or scene description】`.
546- For missing screenshots or data charts, label them as pending replacement assets. Do not fabricate evidence-like visuals.
547
548For every image the cards need:
549
5501. Derive the visual brief from the resolved style (preset palette / user artifact / platform default).
5512. Pick the tool that best preserves the style:
552 - `generate_image` — preferred when the preset or user artifact implies a specific illustrative language. Pass the style cues explicitly in the prompt (color tokens, mood words, composition, negative prompts for styles to avoid).
553 - `image_search` — acceptable for neutral, topic-driven photography or real-world references. Use batch mode (one call, multiple requirements). Before accepting any returned image, verify with `visual_understanding` that its colors, lighting, and composition do not fight the style; discard mismatches rather than force-fit.
554 - `visual_understanding` — also used to read the dimensions / content of any user-supplied reference image before placing it into a card.
5553. Save the files:
556 - Card-local → `posts/<post_id>/assets/<name>.<ext>`.
557 - Cross-post → `shared/<name>.<ext>`.
558
559**4.4 Write the content**
560
561Load [Human Writing Style](./references/human-writing-style.md) before drafting card copy or article prose. This reference is the internal source of truth for human texture, author voice, anti-generic-copy checks, and platform-specific writing self-checks.
562
563**4.4.0 Build the human-writing brief**
564
565Before authoring HTML, write a short internal brief from the available context:
566
567- author voice: who is speaking and why the reader should trust this voice
568- target reader: the concrete reader state, pain, desire, or decision moment
569- reader action: save, comment, follow, consult, compare, try, buy, or remember a viewpoint
570- evidence: uploaded references, product details, screenshots, comparisons, cases, constraints, or observed scenes
571
572Infer from `global.author`, `global.brandPosition`, `global.targetAudience`, optional `__brand/brand-config.json`, `articles[].style`, `articles[].notes`, title, outline, and uploaded materials. Ask only when the missing answer changes the direction of the post and no brand config fallback can answer it. Do not invent first-person experience, customer proof, metrics, or quotes to create human texture.
573
574**4.4.1 Author the platform content**
575
576**For `rednote` / `instagram`:** use `write_file` to author each card HTML at the exact path declared in `cards`. Match the resolved style:
577
578- Preset chosen → link the copied CSS/JS from `../../../shared/presets/<preset>/`, follow its class naming conventions, reuse its tokens.
579- User artifact → reproduce layout, colors, typography, and component treatments faithfully.
580- No preset and no artifact → follow the Platform Defaults and the constraints in [references/card-html-constraints.md](./references/card-html-constraints.md).
581
582Reference only local image files saved in 4.3. Load [Card HTML Constraints](./references/card-html-constraints.md) for the full technical rules, content density requirements, and minimal HTML skeleton before writing any card.
583
584**For `wechat-official-accounts`:** use `write_file` to author the article HTML at the path declared in `post.jso
585
586…(truncated)