diff --git a/AGENTS.md b/AGENTS.md index 202e67f..d8e4a8b 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -17,7 +17,7 @@ npm run typecheck # tsc --noEmit on @opencanva/core ``` - The demo app runs the CLI directly: `opencanva ` (defaults to `dev`). Regenerate the committed skills with **`npm run sync`** (it runs in `apps/demo`); bare `opencanva sync` inside this monorepo is refused (it would write a stray skills tree). -- `npm run sync` copies the skills bundled in `packages/core/skills/` into the demo workspace's **`.agents/skills/`** (vendor-neutral, committed) **and `.claude/skills/`** (Claude-specific, git-ignored): `canva-authoring`, `create-design`, `apply-comments`, `current-design`, `create-theme`, `svg-illustration`. +- `npm run sync` copies the skills bundled in `packages/core/skills/` into the demo workspace's **`.agents/skills/`** (vendor-neutral, committed) **and `.claude/skills/`** (Claude-specific, git-ignored): `canva-authoring`, `create-design`, `write-marketing-copy`, `select-marketing-image`, `design-marketing-cover`, `apply-comments`, `current-design`, `create-theme`, `svg-illustration`. - `opencanva init [dir]` scaffolds a fresh OpenCanva project (config, starter design, and both skill dirs) so a new project is multi-agent ready out of the box. - After changing `designPresets` in `packages/core/src/design.ts` (every preset needs `vibe` + `tags`), run **`npm run gen:catalog && npm run sync`** — it regenerates the theme catalog table inside the `create-design` skill from the presets; `check:sync` fails CI if the table is stale. - To typecheck the designs specifically: `npx tsc --noEmit -p apps/demo` (this is what CI runs alongside the core typecheck). @@ -29,7 +29,7 @@ The authoring know-how ships as **Agent Skills** — `SKILL.md` files with YAML (The repo-root `.agents/skills/` holds only `frontend-design` — a third-party design-quality skill vendored for work *on the framework*, tracked in `skills-lock.json`. It is intentionally not part of the bundle `sync`/`init` distribute.) -- **Authoring graphics** (the common task): write/edit files under `designs//`. Read the **`canva-authoring`** skill first — it's the source of truth for the file contract, the object primitives, the coordinate system, and the inspector-compatibility rules. Use **`create-design`** for the new-graphic workflow, **`apply-comments`** to process inspector markers, **`current-design`** to resolve "this design". +- **Authoring graphics** (the common task): write/edit files under `designs//`. Read the **`canva-authoring`** skill first — it's the source of truth for the file contract, the object primitives, the coordinate system, and the inspector-compatibility rules. Use **`create-design`** for the new-graphic workflow, **`write-marketing-copy`** to turn source material into a click/read/share content package, **`select-marketing-image`** to choose and crop the focal image, **`design-marketing-cover`** for cover composition, **`apply-comments`** to process inspector markers, and **`current-design`** to resolve "this design". - If your agent does not auto-discover skills, read `apps/demo/.agents/skills/canva-authoring/SKILL.md` directly before editing any design. ## Working in this repo diff --git a/CLAUDE.md b/CLAUDE.md index 202e67f..d8e4a8b 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -17,7 +17,7 @@ npm run typecheck # tsc --noEmit on @opencanva/core ``` - The demo app runs the CLI directly: `opencanva ` (defaults to `dev`). Regenerate the committed skills with **`npm run sync`** (it runs in `apps/demo`); bare `opencanva sync` inside this monorepo is refused (it would write a stray skills tree). -- `npm run sync` copies the skills bundled in `packages/core/skills/` into the demo workspace's **`.agents/skills/`** (vendor-neutral, committed) **and `.claude/skills/`** (Claude-specific, git-ignored): `canva-authoring`, `create-design`, `apply-comments`, `current-design`, `create-theme`, `svg-illustration`. +- `npm run sync` copies the skills bundled in `packages/core/skills/` into the demo workspace's **`.agents/skills/`** (vendor-neutral, committed) **and `.claude/skills/`** (Claude-specific, git-ignored): `canva-authoring`, `create-design`, `write-marketing-copy`, `select-marketing-image`, `design-marketing-cover`, `apply-comments`, `current-design`, `create-theme`, `svg-illustration`. - `opencanva init [dir]` scaffolds a fresh OpenCanva project (config, starter design, and both skill dirs) so a new project is multi-agent ready out of the box. - After changing `designPresets` in `packages/core/src/design.ts` (every preset needs `vibe` + `tags`), run **`npm run gen:catalog && npm run sync`** — it regenerates the theme catalog table inside the `create-design` skill from the presets; `check:sync` fails CI if the table is stale. - To typecheck the designs specifically: `npx tsc --noEmit -p apps/demo` (this is what CI runs alongside the core typecheck). @@ -29,7 +29,7 @@ The authoring know-how ships as **Agent Skills** — `SKILL.md` files with YAML (The repo-root `.agents/skills/` holds only `frontend-design` — a third-party design-quality skill vendored for work *on the framework*, tracked in `skills-lock.json`. It is intentionally not part of the bundle `sync`/`init` distribute.) -- **Authoring graphics** (the common task): write/edit files under `designs//`. Read the **`canva-authoring`** skill first — it's the source of truth for the file contract, the object primitives, the coordinate system, and the inspector-compatibility rules. Use **`create-design`** for the new-graphic workflow, **`apply-comments`** to process inspector markers, **`current-design`** to resolve "this design". +- **Authoring graphics** (the common task): write/edit files under `designs//`. Read the **`canva-authoring`** skill first — it's the source of truth for the file contract, the object primitives, the coordinate system, and the inspector-compatibility rules. Use **`create-design`** for the new-graphic workflow, **`write-marketing-copy`** to turn source material into a click/read/share content package, **`select-marketing-image`** to choose and crop the focal image, **`design-marketing-cover`** for cover composition, **`apply-comments`** to process inspector markers, and **`current-design`** to resolve "this design". - If your agent does not auto-discover skills, read `apps/demo/.agents/skills/canva-authoring/SKILL.md` directly before editing any design. ## Working in this repo diff --git a/README.md b/README.md index a933e6e..619998a 100644 --- a/README.md +++ b/README.md @@ -65,7 +65,8 @@ export default [Poster] satisfies Scene[]; - **Click-to-source.** Every object you click resolves to the exact ``/`` in your source (via injected `data-ox-loc` read off the React fiber — works across files and components). Drag/resize/recolor rewrite the object's props **in place** through a dev-only write-back API; the source stays byte-stable so HMR is surgical. - **Comments → edits.** Leave a `@canva-comment` on any object; the bundled `apply-comments` skill applies them. - **Current-design pointer.** The dev server writes `.opencanva/current.json` so an agent can resolve "this design / the object I selected". -- **Works with any agent.** A root `AGENTS.md` (the cross-tool standard read by Codex, Cursor, Copilot, …) carries the repo guide, and `CLAUDE.md` is a byte-identical copy of it (kept in sync by CI). The authoring skills — `canva-authoring`, `create-design`, `apply-comments`, `current-design`, `create-theme`, `svg-illustration` — ship as Agent Skills: `npm run sync` copies them into both `.agents/skills/` (vendor-neutral, committed) and `.claude/skills/` (local). `opencanva init` scaffolds a new project with all of it baked in. +- **Marketing message → image → cover → design.** The bundled `write-marketing-copy` skill creates a truthful click/read/share content package; `select-marketing-image` chooses, ranks, and crops the focal image; `design-marketing-cover` turns both into a thumbnail-tested composition. `create-design` orchestrates the pipeline when the graphic has a marketing goal. +- **Works with any agent.** A root `AGENTS.md` (the cross-tool standard read by Codex, Cursor, Copilot, …) carries the repo guide, and `CLAUDE.md` is a byte-identical copy of it (kept in sync by CI). The nine authoring skills — `canva-authoring`, `create-design`, `write-marketing-copy`, `select-marketing-image`, `design-marketing-cover`, `apply-comments`, `current-design`, `create-theme`, `svg-illustration` — ship as Agent Skills: `npm run sync` copies them into both `.agents/skills/` (vendor-neutral, committed) and `.claude/skills/` (local). `opencanva init` scaffolds a new project with all of it baked in. ## Layout diff --git a/apps/demo/.agents/skills/create-design/SKILL.md b/apps/demo/.agents/skills/create-design/SKILL.md index 138b861..6f1b671 100644 --- a/apps/demo/.agents/skills/create-design/SKILL.md +++ b/apps/demo/.agents/skills/create-design/SKILL.md @@ -7,6 +7,14 @@ description: Use this skill when the user wants to create, draft, design, or gen This skill owns the **workflow** for making a new graphic. The technical reference — file contract, object primitives, coordinate system, design tokens — lives in the **`canva-authoring`** skill. Read that before writing code. You only write files under `designs//`; never modify `package.json`, `opencanva.config.ts`, or other designs. +## Step 0 — Build the marketing message when needed + +If the graphic must earn clicks, reading, saves, or shares—a social post, ad, campaign carousel, launch graphic, cover, or thumbnail—read **`write-marketing-copy`** first and turn the user's source into a `ContentPack`. Settle the audience, one truthful promise, title, cover copy, body/board outline, proof, and CTA before composing the visual. + +If the first board is a cover or thumbnail and its focal image is not locked, read **`select-marketing-image`** and settle an `ImageSelectionPack`. Then read **`design-marketing-cover`** for the stop/click strategy, cover copy tests, layout pattern, and thumbnail audit. This skill still owns the OpenCanva creation workflow. + +Skip this branch for graphics whose purpose is purely decorative or where the user has already locked the exact copy and cover direction. + ## Step 1 — Clarify the brief (ask before designing) Use `AskUserQuestion` to lock in, unless the user's message already answers them: diff --git a/apps/demo/.agents/skills/design-marketing-cover/SKILL.md b/apps/demo/.agents/skills/design-marketing-cover/SKILL.md new file mode 100644 index 0000000..3bab204 --- /dev/null +++ b/apps/demo/.agents/skills/design-marketing-cover/SKILL.md @@ -0,0 +1,113 @@ +--- +name: design-marketing-cover +description: Plan, create, or improve a marketing cover or thumbnail that earns attention, communicates relevance, and converts the right viewer without deceptive clickbait. Use for Xiaohongshu covers, social post covers, video thumbnails, carousel first boards, ad hero graphics, cover copy, cover A/B variants, or before create-design when the first board must drive clicks and reading. +--- + +# Design a marketing cover + +Design the cover as a two-stage decision: the visual makes the right person pause; the words give them a truthful reason to enter. Optimize for qualified attention and promise match, not beauty or curiosity in isolation. + +`create-design` owns the new-design workflow and `canva-authoring` owns the React/file contract. This skill owns the cover composition. Read `canva-authoring` before editing any file under `designs/`. If the title, promise, or body is not settled, use `write-marketing-copy` first. If the focal image is not locked, use `select-marketing-image` before composing the cover. + +## Establish the click contract + +Extract these fields from the request or its `ContentPack`: + +- audience and recognizable situation; +- one-sentence promise; +- proof or result actually present in the content; +- desired action after the click; +- channel and aspect ratio; +- brand or creator memory anchors; +- available photos, screenshots, product images, or illustrations. + +Reject a cover concept if the body cannot pay it off. Never fake a result image, endorsement, transformation, scarcity cue, UI state, or emotional reaction. + +For Xiaohongshu, read [references/xiaohongshu.md](references/xiaohongshu.md). + +## Resolve the focal image + +Consume the `ImageSelectionPack` from `select-marketing-image`: selected asset, evidence boundary, focal point, essential region, text-safe zone, crop, treatment, rights/privacy status, and validation status. + +If the user has already locked an image, verify that it matches the promise and can survive the target crop. Do not replace it merely because another option is prettier. If it is misleading, unusable, or unlicensed, explain the conflict and use `select-marketing-image` to find a truthful alternative. + +## Write cover copy with three tests + +The cover copy must answer, at a glance: + +1. **Is this about me?** Name the person, moment, task, or symptom. +2. **What do I gain or avoid?** Make the practical value visible. +3. **Why open this one?** Surface credible specificity, a gap, proof, or an unresolved tension. + +Keep cover copy shorter than the title. Do not repeat the title verbatim. Use a short eyebrow or proof chip only when it adds a distinct piece of information. + +## Pick a layout pattern + +- **Sandwich:** headline above, focal person/object in the middle, payoff or proof below. Use for a strong portrait or product. +- **Information center:** one large text block integrated with the image. Use when rapid comprehension matters more than atmosphere. +- **Top/bottom:** headline in one zone, supporting line or proof in the other, with the visual carrying the center. Use for clean repeatable series. +- **Four-corner:** distribute very short text around a strong central image. Use only when every corner remains legible and the image has enough negative space. + +Choose the simplest pattern that preserves the image and the promise. Do not fill every empty area. + +## Build it in OpenCanva + +Follow `create-design` for id, theme, scene, and handoff; follow `canva-authoring` for primitives and source-safe coordinates. Additionally: + +- Make one element dominant: the focal image or the headline, not both at equal weight. +- Keep the reading order obvious at thumbnail size: context → promise → proof. +- Put text on a quiet region, solid panel, gradient/scrim, or high-contrast crop. +- Use high contrast based on the actual background. Yellow can attract attention only when it still contrasts; it is not a universal rule. +- Control line breaks. Keep the key phrase together and remove words before shrinking it into illegibility. +- Keep essential text and faces away from likely UI overlays and crop edges. +- Use named groups such as `FocalImage`, `Headline`, `Proof`, and `BrandAnchor`. +- Reuse a stable visual anchor—type treatment, framing device, color, or recurring position—when the user is building a recognizable series. + +View the result at fitted zoom and at roughly 25% size. If the promise cannot be understood at the smaller view, simplify it. + +## Create variants that teach something + +When the user asks for options or the concept is high-stakes, create two or three labeled Scene variants. Keep the promise and brand constant; change only one major variable per variant: + +- focal image; +- copy angle; +- layout; +- contrast treatment. + +Do not create cosmetic variants that cannot reveal why one performs better. Once a pattern performs well, reuse its core structure until evidence supports changing it. + +## Deliver a CoverSpec + +Before or alongside implementation, capture: + +```md +## CoverSpec +- Audience / situation: +- Channel / dimensions: +- Promise paid off by: +- Selected asset / source mode: +- Focal image / crop: +- Essential region / text-safe zone: +- Cover copy: +- Supporting proof or eyebrow: +- Layout pattern: +- Reading order: +- Contrast treatment: +- Brand anchor: +- Optional test variable: +``` + +## Two-second audit + +Score each item 0–2: + +- **Pause:** the visual has a clear focal reason to stop. +- **Relevance:** the right viewer recognizes themselves. +- **Value:** the benefit or avoided cost is concrete. +- **Reason to click:** specificity, proof, or tension remains after the topic is understood. +- **Legibility:** the message survives thumbnail size and likely UI crops. +- **Promise match:** the underlying content pays off the cover early. + +Revise below 10/12. Treat a 0 on relevance, legibility, or promise match as a hard failure regardless of total score. Finally run the OpenCanva layout lint; a marketing cover is not done with hidden, crowded, occluded, or off-canvas content. + +Do not award a final **Pause** or **Legibility** score to an unrendered `CoverSpec`. Mark those items `provisional` until the cover has been viewed at fitted zoom and thumbnail size. A written intention is not visual verification. diff --git a/apps/demo/.agents/skills/design-marketing-cover/agents/openai.yaml b/apps/demo/.agents/skills/design-marketing-cover/agents/openai.yaml new file mode 100644 index 0000000..195d2a6 --- /dev/null +++ b/apps/demo/.agents/skills/design-marketing-cover/agents/openai.yaml @@ -0,0 +1,4 @@ +interface: + display_name: "Design Marketing Cover" + short_description: "Design clear, clickable covers that keep their promise" + default_prompt: "Use $design-marketing-cover to turn my content into a clickable, trustworthy social cover." diff --git a/apps/demo/.agents/skills/design-marketing-cover/references/xiaohongshu.md b/apps/demo/.agents/skills/design-marketing-cover/references/xiaohongshu.md new file mode 100644 index 0000000..c8bcb35 --- /dev/null +++ b/apps/demo/.agents/skills/design-marketing-cover/references/xiaohongshu.md @@ -0,0 +1,40 @@ +# Xiaohongshu cover reference + +Use this reference for Xiaohongshu note covers. Treat it as a practical creative heuristic, not a guarantee about distribution. + +## Format and roles + +- Default a portrait note cover to 3:4, commonly 1080×1440, unless the user's publishing workflow requires another size. +- Treat the image as the stopping device and the overlay copy as the clicking reason. +- Design for a two-column discovery feed and test the cover at small size. +- Make the cover and note title complementary. The title can carry topic/search context while the cover carries self-relevance, payoff, or tension. + +## Strong focal image options + +1. A high-contrast scene with a clear social or visual tension. +2. A genuine emotional close-up relevant to the content. +3. A visible, source-supported outcome or comparison. +4. A first-person view that puts the reader inside the task. + +Prefer self-insertion over generic prettiness. The viewer should recognize a situation they want, fear, or already experience. + +## Overlay copy + +Check three questions: + +- Does the target reader know it concerns them? +- Is the gain or avoided mistake visible? +- Is there a credible reason this specific note is worth opening? + +Use high contrast against the real image region. A bright yellow accent is common and can attract attention, but switch colors whenever it loses contrast or clashes with the brand. + +## Layout patterns + +- Sandwich: headline / face or object / payoff. +- Information center: large message integrated across the composition. +- Top/bottom: primary line above, secondary proof below. +- Four-corner: short fragments around a clean central image; reserve for images with strong negative space. + +## Series behavior + +Keep a successful cover grammar recognizable across a series: stable type, crop logic, color cue, and information order. Test one major variable at a time instead of changing the entire style every post. diff --git a/apps/demo/.agents/skills/select-marketing-image/SKILL.md b/apps/demo/.agents/skills/select-marketing-image/SKILL.md new file mode 100644 index 0000000..ffd2e25 --- /dev/null +++ b/apps/demo/.agents/skills/select-marketing-image/SKILL.md @@ -0,0 +1,162 @@ +--- +name: select-marketing-image +description: Choose, rank, and crop the strongest truthful image for marketing content, covers, thumbnails, ads, and carousel first boards. Use when comparing candidate photos, screenshots, product shots, stock images, illustrations, or generated images; when deciding what kind of visual to source or shoot; when an image needs a crop and text-safe zone; or before design-marketing-cover when the focal image is not locked. Produces an ImageSelectionPack and can provide a capture brief, search queries, or generation prompt when no usable asset exists. +--- + +# Select a marketing image + +Choose the image that best carries the content promise at feed speed. Optimize for qualified attention, self-recognition, credibility, and usable composition—not generic beauty. + +`write-marketing-copy` owns the promise and `design-marketing-cover` owns the final cover composition. This skill owns the focal-image decision between them. Do not edit a design unless the user also asks for implementation. + +## Read the content contract + +Consume the request or its `ContentPack` and establish: + +- audience and recognizable situation; +- one truthful promise; +- proof or outcome actually present; +- channel, dimensions, and likely UI crop; +- cover copy and approximate text load; +- brand, creator identity, and desired feeling; +- available assets and their provenance. + +If the promise is unsettled, use `write-marketing-copy` first. Ask only when a missing fact would change truthfulness, permissions, or the image direction; otherwise state an assumption and proceed. + +If the current platform dimensions or UI safe areas are not supplied by the user or maintained in a local reference, verify them against an authoritative current source before presenting them as facts. Otherwise label them as working assumptions. + +For Xiaohongshu, read [references/xiaohongshu.md](references/xiaohongshu.md). + +## Define the image's job + +Choose one primary job before looking for a picture: + +1. **Recognition** — make the audience see their situation or desired identity. +2. **Proof** — show the real outcome, artifact, comparison, or evidence. +3. **Emotion** — make the relevant feeling instantly legible. +4. **Mechanism** — show how the task, method, or product works. +5. **Context** — place a person or product inside a credible real-world use case. + +Do not ask one image to carry every job. Prefer the job that supports the promise with the strongest available evidence. + +## Choose the source mode + +Match the source to what the image is claiming: + +- **User-owned photo:** prefer for identity, lived experience, personal result, and trust. +- **Screenshot or artifact:** prefer for software, workflows, documents, outcomes, and demonstrations; hide private or sensitive data. +- **Real product in use:** prefer over an isolated product shot when the promise is contextual or functional. +- **Licensed stock:** use for a representative situation, never as implied proof or testimony. Record the source and license status. +- **Generated image or illustration:** use for a concept or representative scene, never as documentary evidence. Disclose the synthetic nature when it could be mistaken for a real event, person, or result. +- **Type-led or graphic cover:** choose when no image can add truthful, specific value. Do not force a decorative photo. + +Never assume an image found online is licensed for reuse. + +## Write the ImageBrief + +Specify the selection target before sourcing or ranking: + +```md +## ImageBrief +- Image job: +- Subject: +- Action / moment: +- Environment: +- Point of view: +- Emotion / state: +- Evidence boundary: +- Desired focal placement: +- Text-safe zone: +- Target crop(s): +- Brand cues: +- Must include: +- Must avoid: +``` + +Use observable direction. Replace “professional and engaging” with details such as “first-person view of a manager's notebook across from a teammate; open space in the upper left; laptop closed.” + +## Inspect candidates + +Inspect every candidate you rank. Do not infer the contents of an unopened file, URL, contact sheet, or unseen gallery. View important finalists at full size and at approximate feed-thumbnail size. + +Reject a candidate before scoring when it: + +- contradicts the content or implies unsupported proof, transformation, endorsement, or emotion; +- exposes private information, confidential UI, or an identifiable person without suitable permission; +- has unknown or unsuitable usage rights for the intended publication; +- is generic enough to fit unrelated content equally well; +- lacks one clear subject or loses the essential action at the target crop; +- is too small, blurred, watermarked, artifacted, or visibly malformed for the output; +- contains baked-in text or branding that conflicts with the cover; +- cannot leave usable space for the required copy, even with a crop, panel, or scrim. + +## Rank viable candidates + +Score each viable candidate 0–2 and apply the weights below. Use the score to make reasoning explicit, not to predict click-through rate. + +- **0:** absent, contradictory, misleading, or unusable. +- **1:** plausible but generic, inferred, weak at thumbnail size, or dependent on a repair. +- **2:** specific, immediately visible in the asset, and strong without needing an explanatory caption. + +| Dimension | Weight | Question | +| --- | ---: | --- | +| Promise relevance | ×3 | Does it visually support the exact promise? | +| Authenticity / proof fit | ×3 | Is the implied claim honest for this source mode? | +| Audience self-recognition | ×2 | Will the intended viewer recognize their situation or desire? | +| Focal stopping power | ×2 | Is there one immediately legible subject, contrast, or moment? | +| Thumbnail clarity | ×2 | Does the essential meaning survive at small size? | +| Text-safe composition | ×1 | Can the required copy sit clearly without hiding the subject? | +| Crop resilience | ×1 | Can it survive the target ratio and likely variants? | +| Brand fit | ×1 | Does it feel credible for this creator or brand? | + +Maximum: 30. Treat 24–30 as strong, 20–23 as usable with a clear fix, and below 20 as a signal to source again. Reject any candidate scoring 0 on promise relevance, authenticity, or thumbnail clarity regardless of total. Break ties in that order, then use focal stopping power. + +Show the per-dimension scores, not only a total. A common stock metaphor or visual cliché—generic handshake, generic meeting, floating product, anonymous smiling person—cannot receive 2 for promise relevance, self-recognition, or focal stopping power unless concrete details in the asset make it specific to this promise. Do not award specificity supplied only by the brief or cover text. + +## Plan the crop and treatment + +For the selected image, specify: + +- target aspect ratio and any size variants; +- focal point as approximate `x% / y%` within the original; +- essential region that must survive the crop; +- preferred text-safe zone and reading direction; +- whether a crop, blur, scrim, gradient, or solid panel is needed; +- whether the subject's gaze or motion helps lead toward the copy; +- fallback crop if platform UI or responsive variants cover the first choice. + +Never crop out the evidence that made the image relevant. Do not use heavy treatment to rescue an image whose subject or meaning is wrong. + +## Source when no candidate works + +Choose one primary next action: + +- **Capture brief:** give a shot list with subject, action, viewpoint, light, background, negative space, and avoid list. +- **Search queries:** describe content literally—subject + action + environment + point of view + composition. Provide 3–5 queries and require a license check. +- **Generation prompt:** describe the same concrete scene, composition, crop, negative space, and exclusions. Label the result as representative, not evidence. +- **Graphic fallback:** recommend a screenshot, artifact, diagram, or type-led cover when a photo would be decorative or misleading. + +Do not silently switch from real evidence to a generated substitute. + +## Deliver an ImageSelectionPack + +```md +## ImageSelectionPack +- Audience / promise: +- Image job: +- Source mode / provenance: +- Selected asset: +- Why it wins: +- Evidence boundary: +- Candidate ranking and rejection reasons: +- Target crop / focal point: +- Essential region: +- Text-safe zone: +- Recommended treatment: +- Rights / privacy status: +- Fallback asset or crop: +- Capture brief, search queries, or generation prompt if needed: +- Validation status: proposed / inspected / crop-previewed / rendered +``` + +Hand this pack to `design-marketing-cover`. Keep **proposed** separate from **inspected**: never claim thumbnail clarity, crop safety, resolution, or visual quality for an asset that has not actually been viewed. diff --git a/apps/demo/.agents/skills/select-marketing-image/agents/openai.yaml b/apps/demo/.agents/skills/select-marketing-image/agents/openai.yaml new file mode 100644 index 0000000..875131f --- /dev/null +++ b/apps/demo/.agents/skills/select-marketing-image/agents/openai.yaml @@ -0,0 +1,4 @@ +interface: + display_name: "Select Marketing Image" + short_description: "Choose credible images that earn attention and fit the copy" + default_prompt: "Use $select-marketing-image to choose and crop the strongest image for my marketing content." diff --git a/apps/demo/.agents/skills/select-marketing-image/references/xiaohongshu.md b/apps/demo/.agents/skills/select-marketing-image/references/xiaohongshu.md new file mode 100644 index 0000000..c884388 --- /dev/null +++ b/apps/demo/.agents/skills/select-marketing-image/references/xiaohongshu.md @@ -0,0 +1,31 @@ +# Xiaohongshu image-selection reference + +Use this reference for Xiaohongshu note covers. Treat these as creative heuristics, not guarantees about distribution. + +## Feed conditions + +- Default a portrait cover to 3:4, commonly 1080×1440, unless the publishing workflow specifies otherwise. +- Judge the candidate inside a small two-column-feed preview, not only at full resolution. +- Preserve the main subject, result, and essential gesture inside the target crop with room for short overlay copy. +- Keep important faces, hands, evidence, and text-safe regions away from likely crop edges and UI overlays. + +## Useful image jobs + +- **Contrast scene:** a real visual or social contrast that creates immediate tension. +- **Emotional close-up:** a genuine expression that is directly relevant to the note. +- **Visible outcome:** a source-supported result, artifact, or comparison. +- **First-person immersion:** hands, workspace, screen, environment, or an over-the-shoulder view that puts the reader inside the task. +- **Product in use:** the product solving the recognizable situation rather than floating as decoration. + +Prefer self-insertion over generic prettiness. The selected image should help the target reader think “this concerns me” before they read every word. + +## Source boundaries + +- Do not use stock or generated people as implied personal testimony. +- Do not fabricate before/after evidence or emotional reactions. +- Treat screenshots as evidence: preserve the relevant UI while removing private data. +- Use a type-led cover when no available image is both specific and truthful. + +## Series behavior + +When several posts belong to one series, keep the crop grammar, focal placement, light, or recurring environment recognizable. Test a different image hypothesis without changing every other cover variable at the same time. diff --git a/apps/demo/.agents/skills/write-marketing-copy/SKILL.md b/apps/demo/.agents/skills/write-marketing-copy/SKILL.md new file mode 100644 index 0000000..0a53e11 --- /dev/null +++ b/apps/demo/.agents/skills/write-marketing-copy/SKILL.md @@ -0,0 +1,137 @@ +--- +name: write-marketing-copy +description: Turn rough source material into truthful, high-retention marketing copy for social posts, carousels, ads, launch graphics, and campaign content. Use when the user wants stronger hooks, titles, cover text, readable body copy, calls to action, shareable framing, Xiaohongshu copy, or a content package that OpenCanva can design. Also use before create-design when a graphic must win attention and sustain reading. +--- + +# Write marketing copy + +Convert the user's source into a content package that earns attention, keeps its promise, and is easy to lay out. Treat copy as a sequence—discovery, click, read-through, trust, then action—not as one undifferentiated paragraph. + +## Protect the promise + +- Preserve the source's facts, qualifications, and causal limits. +- Never invent results, testimonials, credentials, urgency, scarcity, or authority. +- Mark missing proof as a question or placeholder; do not silently fill it. +- Make the title and cover compelling by selecting a sharp truthful angle, not by overstating the content. +- Ensure every promise made before the click is paid off early in the body. + +## Build the brief + +Extract or infer these fields before writing: + +- **Audience:** who should immediately recognize themselves? +- **Current state:** what are they trying, feeling, fearing, or misunderstanding? +- **Desired change:** what useful outcome can this content honestly deliver? +- **Source truth:** which facts, examples, stories, and claims may be used? +- **Goal:** click, read, save, share, reply, sign up, or buy? +- **Channel:** Xiaohongshu, Instagram, LinkedIn, ad, landing graphic, or a generic social post? +- **Voice:** the user's natural tone, brand voice, or supplied reference samples. + +Ask only for a missing input that would materially change the result. Otherwise state a concise assumption and proceed. When the target is Xiaohongshu, read [references/xiaohongshu.md](references/xiaohongshu.md). + +## Choose one content angle + +Express the angle as: + +> For **[audience in a recognizable situation]**, show **[specific useful change]** through **[credible mechanism or proof]**, so they can **[action or identity payoff]**. + +Prefer an angle that scores well on: + +1. **Relevance** — the intended reader recognizes “this is for me.” +2. **Specificity** — the situation and payoff are concrete. +3. **Tension** — there is a gap, surprise, mistake, tradeoff, or unresolved question. +4. **Credibility** — the source contains enough proof to support it. +5. **Share motive** — sharing helps someone, signals identity, or gives language to a felt experience. + +Do not combine several weak promises. Pick one dominant promise and make the rest supporting points. + +## Write the discovery package + +Draft three meaningfully different candidates, then select one. Vary the mechanism, not just synonyms: + +- **Benefit:** state what the reader can gain. +- **Pain:** name a familiar costly problem. +- **Relief:** offer a simpler, faster, or less painful route without false ease. +- **Recognition:** articulate a feeling or situation the audience has not named clearly. +- **Contrarian:** challenge a familiar belief only when the body can prove the reversal. +- **Authority:** borrow a study, expert, or institution only when the source is verifiable and accurately represented. +- **Emotion:** lead with delight, frustration, fear, hope, or surprise without manipulating or shaming. + +For each candidate, write: + +- **Title:** carries topic, searchable language, and the main frame. +- **Cover copy:** creates immediate self-relevance and a reason to click. +- **Hook:** pays off the promise in the first lines instead of repeating the title. + +Do not make title and cover copy identical. Let them add information to each other while pointing to the same promise. + +## Structure for read-through + +Use the shortest structure that fully delivers the value: + +1. **Hook:** recognition, outcome, tension, or a concrete scene. +2. **Orientation:** tell the reader what they will get and why this source is worth their time. +3. **Value units:** one idea per paragraph, card, or carousel board; front-load the useful sentence. +4. **Proof:** example, demonstration, comparison, result, source, or clearly labeled personal experience. +5. **Payoff:** restate the change in practical terms. +6. **CTA:** request one natural next action that follows from the content. + +For a story, use **setup → obstacle → turn → change → transferable takeaway**. Include only details that increase understanding, emotion, or credibility. + +## Make the copy easy to read + +- Use short sentences and one idea per block. +- Replace abstractions with observable situations, actions, objects, and numbers from the source. +- Put the conclusion before the explanation when the reader needs the answer first. +- Use headings and lists as navigation, not decoration. +- Remove throat-clearing, duplicate claims, generic motivation, and empty superlatives. +- Preserve useful nuance, but move caveats next to the claim they qualify. +- Match the audience's language; prefer the words they search or say over industry jargon. + +## Keep a human voice + +When samples exist, extract recurring traits—sentence length, rhythm, vocabulary, stance, humor, and favorite transitions—then write with those constraints. Never imitate a living creator's distinctive style on request; use high-level traits to create an original voice. + +After drafting: + +- Replace stock AI transitions and perfectly symmetrical phrasing. +- Add only source-grounded observations, minor texture, and natural rhythm. +- Read aloud and simplify anything a person would not naturally say. +- Keep deliberate roughness subtle; clarity matters more than forced slang. + +## Deliver a ContentPack + +Return or maintain this compact handoff for `create-design` and `design-marketing-cover`: + +```md +## ContentPack +- Audience: +- Channel / goal: +- One-sentence promise: +- Selected angle: +- Title: +- Cover copy: +- Hook: +- Body / board outline: +- Proof available: +- CTA: +- Search phrases: +- Voice notes: +- Source boundaries / assumptions: +- Claims needing confirmation: +- Alternate title + cover pairs: +``` + +Then provide the publishable copy. Keep analysis outside the copy so the user can paste the finished text directly. + +## Final audit + +Confirm all of the following: + +- The intended reader can recognize relevance in two seconds. +- The title and cover make one clear, supported promise. +- The opening pays off that promise immediately. +- Each section advances the reader instead of restating the premise. +- Facts and proof trace back to the user's source. +- The CTA asks for one proportionate action. +- A reader has a concrete reason to save or share it. diff --git a/apps/demo/.agents/skills/write-marketing-copy/agents/openai.yaml b/apps/demo/.agents/skills/write-marketing-copy/agents/openai.yaml new file mode 100644 index 0000000..0933639 --- /dev/null +++ b/apps/demo/.agents/skills/write-marketing-copy/agents/openai.yaml @@ -0,0 +1,4 @@ +interface: + display_name: "Write Marketing Copy" + short_description: "Turn source material into readable, clickable social copy" + default_prompt: "Use $write-marketing-copy to turn my source material into a high-retention social content package." diff --git a/apps/demo/.agents/skills/write-marketing-copy/references/xiaohongshu.md b/apps/demo/.agents/skills/write-marketing-copy/references/xiaohongshu.md new file mode 100644 index 0000000..72e7fa4 --- /dev/null +++ b/apps/demo/.agents/skills/write-marketing-copy/references/xiaohongshu.md @@ -0,0 +1,36 @@ +# Xiaohongshu copy reference + +Use this reference only when Xiaohongshu is the target. Treat it as an editorial heuristic, not a guarantee about the platform algorithm. + +## Discovery and search + +- Write for both recommendation discovery and active search. +- Put the audience's natural search phrase in the title when it fits. Prefer “how to take better photos” language over specialist terminology such as “composition theory.” +- Mine the user's source, audience questions, comments, support requests, and reviews for real phrasing. Do not keyword-stuff. +- Let the title establish the topic and angle; let cover copy add relevance, benefit, or tension. + +## Useful title frames + +- Benefit: “A practical way to …” +- Pain: “If you keep getting stuck at …” +- Relief: “The lower-friction way I …” +- Recognition: “You are not bad at X; you may be missing Y.” +- Contrarian: “What looks like X may actually be Y.” +- Evidence: “What changed after …” + +Keep the title faithful to the note. Avoid absolute claims unless the source genuinely proves them. + +## Read-through + +- Deliver the promised answer in the opening lines. +- Keep paragraphs short enough to scan on a phone. +- Use one useful idea per paragraph or carousel board. +- Prefer concrete scenes, comparisons, checklists, and examples over generic advice. +- Close with one context-appropriate action: save for later, share with a specific person, answer a real question, or try one step. + +## Human voice + +- Build voice from the user's own samples when available. +- Use conversational wording without manufacturing slang. +- Vary rhythm and remove generic AI transitions. +- Never invent a personal story to create “authenticity.” diff --git a/packages/core/skills/create-design/SKILL.md b/packages/core/skills/create-design/SKILL.md index 138b861..6f1b671 100644 --- a/packages/core/skills/create-design/SKILL.md +++ b/packages/core/skills/create-design/SKILL.md @@ -7,6 +7,14 @@ description: Use this skill when the user wants to create, draft, design, or gen This skill owns the **workflow** for making a new graphic. The technical reference — file contract, object primitives, coordinate system, design tokens — lives in the **`canva-authoring`** skill. Read that before writing code. You only write files under `designs//`; never modify `package.json`, `opencanva.config.ts`, or other designs. +## Step 0 — Build the marketing message when needed + +If the graphic must earn clicks, reading, saves, or shares—a social post, ad, campaign carousel, launch graphic, cover, or thumbnail—read **`write-marketing-copy`** first and turn the user's source into a `ContentPack`. Settle the audience, one truthful promise, title, cover copy, body/board outline, proof, and CTA before composing the visual. + +If the first board is a cover or thumbnail and its focal image is not locked, read **`select-marketing-image`** and settle an `ImageSelectionPack`. Then read **`design-marketing-cover`** for the stop/click strategy, cover copy tests, layout pattern, and thumbnail audit. This skill still owns the OpenCanva creation workflow. + +Skip this branch for graphics whose purpose is purely decorative or where the user has already locked the exact copy and cover direction. + ## Step 1 — Clarify the brief (ask before designing) Use `AskUserQuestion` to lock in, unless the user's message already answers them: diff --git a/packages/core/skills/design-marketing-cover/SKILL.md b/packages/core/skills/design-marketing-cover/SKILL.md new file mode 100644 index 0000000..3bab204 --- /dev/null +++ b/packages/core/skills/design-marketing-cover/SKILL.md @@ -0,0 +1,113 @@ +--- +name: design-marketing-cover +description: Plan, create, or improve a marketing cover or thumbnail that earns attention, communicates relevance, and converts the right viewer without deceptive clickbait. Use for Xiaohongshu covers, social post covers, video thumbnails, carousel first boards, ad hero graphics, cover copy, cover A/B variants, or before create-design when the first board must drive clicks and reading. +--- + +# Design a marketing cover + +Design the cover as a two-stage decision: the visual makes the right person pause; the words give them a truthful reason to enter. Optimize for qualified attention and promise match, not beauty or curiosity in isolation. + +`create-design` owns the new-design workflow and `canva-authoring` owns the React/file contract. This skill owns the cover composition. Read `canva-authoring` before editing any file under `designs/`. If the title, promise, or body is not settled, use `write-marketing-copy` first. If the focal image is not locked, use `select-marketing-image` before composing the cover. + +## Establish the click contract + +Extract these fields from the request or its `ContentPack`: + +- audience and recognizable situation; +- one-sentence promise; +- proof or result actually present in the content; +- desired action after the click; +- channel and aspect ratio; +- brand or creator memory anchors; +- available photos, screenshots, product images, or illustrations. + +Reject a cover concept if the body cannot pay it off. Never fake a result image, endorsement, transformation, scarcity cue, UI state, or emotional reaction. + +For Xiaohongshu, read [references/xiaohongshu.md](references/xiaohongshu.md). + +## Resolve the focal image + +Consume the `ImageSelectionPack` from `select-marketing-image`: selected asset, evidence boundary, focal point, essential region, text-safe zone, crop, treatment, rights/privacy status, and validation status. + +If the user has already locked an image, verify that it matches the promise and can survive the target crop. Do not replace it merely because another option is prettier. If it is misleading, unusable, or unlicensed, explain the conflict and use `select-marketing-image` to find a truthful alternative. + +## Write cover copy with three tests + +The cover copy must answer, at a glance: + +1. **Is this about me?** Name the person, moment, task, or symptom. +2. **What do I gain or avoid?** Make the practical value visible. +3. **Why open this one?** Surface credible specificity, a gap, proof, or an unresolved tension. + +Keep cover copy shorter than the title. Do not repeat the title verbatim. Use a short eyebrow or proof chip only when it adds a distinct piece of information. + +## Pick a layout pattern + +- **Sandwich:** headline above, focal person/object in the middle, payoff or proof below. Use for a strong portrait or product. +- **Information center:** one large text block integrated with the image. Use when rapid comprehension matters more than atmosphere. +- **Top/bottom:** headline in one zone, supporting line or proof in the other, with the visual carrying the center. Use for clean repeatable series. +- **Four-corner:** distribute very short text around a strong central image. Use only when every corner remains legible and the image has enough negative space. + +Choose the simplest pattern that preserves the image and the promise. Do not fill every empty area. + +## Build it in OpenCanva + +Follow `create-design` for id, theme, scene, and handoff; follow `canva-authoring` for primitives and source-safe coordinates. Additionally: + +- Make one element dominant: the focal image or the headline, not both at equal weight. +- Keep the reading order obvious at thumbnail size: context → promise → proof. +- Put text on a quiet region, solid panel, gradient/scrim, or high-contrast crop. +- Use high contrast based on the actual background. Yellow can attract attention only when it still contrasts; it is not a universal rule. +- Control line breaks. Keep the key phrase together and remove words before shrinking it into illegibility. +- Keep essential text and faces away from likely UI overlays and crop edges. +- Use named groups such as `FocalImage`, `Headline`, `Proof`, and `BrandAnchor`. +- Reuse a stable visual anchor—type treatment, framing device, color, or recurring position—when the user is building a recognizable series. + +View the result at fitted zoom and at roughly 25% size. If the promise cannot be understood at the smaller view, simplify it. + +## Create variants that teach something + +When the user asks for options or the concept is high-stakes, create two or three labeled Scene variants. Keep the promise and brand constant; change only one major variable per variant: + +- focal image; +- copy angle; +- layout; +- contrast treatment. + +Do not create cosmetic variants that cannot reveal why one performs better. Once a pattern performs well, reuse its core structure until evidence supports changing it. + +## Deliver a CoverSpec + +Before or alongside implementation, capture: + +```md +## CoverSpec +- Audience / situation: +- Channel / dimensions: +- Promise paid off by: +- Selected asset / source mode: +- Focal image / crop: +- Essential region / text-safe zone: +- Cover copy: +- Supporting proof or eyebrow: +- Layout pattern: +- Reading order: +- Contrast treatment: +- Brand anchor: +- Optional test variable: +``` + +## Two-second audit + +Score each item 0–2: + +- **Pause:** the visual has a clear focal reason to stop. +- **Relevance:** the right viewer recognizes themselves. +- **Value:** the benefit or avoided cost is concrete. +- **Reason to click:** specificity, proof, or tension remains after the topic is understood. +- **Legibility:** the message survives thumbnail size and likely UI crops. +- **Promise match:** the underlying content pays off the cover early. + +Revise below 10/12. Treat a 0 on relevance, legibility, or promise match as a hard failure regardless of total score. Finally run the OpenCanva layout lint; a marketing cover is not done with hidden, crowded, occluded, or off-canvas content. + +Do not award a final **Pause** or **Legibility** score to an unrendered `CoverSpec`. Mark those items `provisional` until the cover has been viewed at fitted zoom and thumbnail size. A written intention is not visual verification. diff --git a/packages/core/skills/design-marketing-cover/agents/openai.yaml b/packages/core/skills/design-marketing-cover/agents/openai.yaml new file mode 100644 index 0000000..195d2a6 --- /dev/null +++ b/packages/core/skills/design-marketing-cover/agents/openai.yaml @@ -0,0 +1,4 @@ +interface: + display_name: "Design Marketing Cover" + short_description: "Design clear, clickable covers that keep their promise" + default_prompt: "Use $design-marketing-cover to turn my content into a clickable, trustworthy social cover." diff --git a/packages/core/skills/design-marketing-cover/references/xiaohongshu.md b/packages/core/skills/design-marketing-cover/references/xiaohongshu.md new file mode 100644 index 0000000..c8bcb35 --- /dev/null +++ b/packages/core/skills/design-marketing-cover/references/xiaohongshu.md @@ -0,0 +1,40 @@ +# Xiaohongshu cover reference + +Use this reference for Xiaohongshu note covers. Treat it as a practical creative heuristic, not a guarantee about distribution. + +## Format and roles + +- Default a portrait note cover to 3:4, commonly 1080×1440, unless the user's publishing workflow requires another size. +- Treat the image as the stopping device and the overlay copy as the clicking reason. +- Design for a two-column discovery feed and test the cover at small size. +- Make the cover and note title complementary. The title can carry topic/search context while the cover carries self-relevance, payoff, or tension. + +## Strong focal image options + +1. A high-contrast scene with a clear social or visual tension. +2. A genuine emotional close-up relevant to the content. +3. A visible, source-supported outcome or comparison. +4. A first-person view that puts the reader inside the task. + +Prefer self-insertion over generic prettiness. The viewer should recognize a situation they want, fear, or already experience. + +## Overlay copy + +Check three questions: + +- Does the target reader know it concerns them? +- Is the gain or avoided mistake visible? +- Is there a credible reason this specific note is worth opening? + +Use high contrast against the real image region. A bright yellow accent is common and can attract attention, but switch colors whenever it loses contrast or clashes with the brand. + +## Layout patterns + +- Sandwich: headline / face or object / payoff. +- Information center: large message integrated across the composition. +- Top/bottom: primary line above, secondary proof below. +- Four-corner: short fragments around a clean central image; reserve for images with strong negative space. + +## Series behavior + +Keep a successful cover grammar recognizable across a series: stable type, crop logic, color cue, and information order. Test one major variable at a time instead of changing the entire style every post. diff --git a/packages/core/skills/select-marketing-image/SKILL.md b/packages/core/skills/select-marketing-image/SKILL.md new file mode 100644 index 0000000..ffd2e25 --- /dev/null +++ b/packages/core/skills/select-marketing-image/SKILL.md @@ -0,0 +1,162 @@ +--- +name: select-marketing-image +description: Choose, rank, and crop the strongest truthful image for marketing content, covers, thumbnails, ads, and carousel first boards. Use when comparing candidate photos, screenshots, product shots, stock images, illustrations, or generated images; when deciding what kind of visual to source or shoot; when an image needs a crop and text-safe zone; or before design-marketing-cover when the focal image is not locked. Produces an ImageSelectionPack and can provide a capture brief, search queries, or generation prompt when no usable asset exists. +--- + +# Select a marketing image + +Choose the image that best carries the content promise at feed speed. Optimize for qualified attention, self-recognition, credibility, and usable composition—not generic beauty. + +`write-marketing-copy` owns the promise and `design-marketing-cover` owns the final cover composition. This skill owns the focal-image decision between them. Do not edit a design unless the user also asks for implementation. + +## Read the content contract + +Consume the request or its `ContentPack` and establish: + +- audience and recognizable situation; +- one truthful promise; +- proof or outcome actually present; +- channel, dimensions, and likely UI crop; +- cover copy and approximate text load; +- brand, creator identity, and desired feeling; +- available assets and their provenance. + +If the promise is unsettled, use `write-marketing-copy` first. Ask only when a missing fact would change truthfulness, permissions, or the image direction; otherwise state an assumption and proceed. + +If the current platform dimensions or UI safe areas are not supplied by the user or maintained in a local reference, verify them against an authoritative current source before presenting them as facts. Otherwise label them as working assumptions. + +For Xiaohongshu, read [references/xiaohongshu.md](references/xiaohongshu.md). + +## Define the image's job + +Choose one primary job before looking for a picture: + +1. **Recognition** — make the audience see their situation or desired identity. +2. **Proof** — show the real outcome, artifact, comparison, or evidence. +3. **Emotion** — make the relevant feeling instantly legible. +4. **Mechanism** — show how the task, method, or product works. +5. **Context** — place a person or product inside a credible real-world use case. + +Do not ask one image to carry every job. Prefer the job that supports the promise with the strongest available evidence. + +## Choose the source mode + +Match the source to what the image is claiming: + +- **User-owned photo:** prefer for identity, lived experience, personal result, and trust. +- **Screenshot or artifact:** prefer for software, workflows, documents, outcomes, and demonstrations; hide private or sensitive data. +- **Real product in use:** prefer over an isolated product shot when the promise is contextual or functional. +- **Licensed stock:** use for a representative situation, never as implied proof or testimony. Record the source and license status. +- **Generated image or illustration:** use for a concept or representative scene, never as documentary evidence. Disclose the synthetic nature when it could be mistaken for a real event, person, or result. +- **Type-led or graphic cover:** choose when no image can add truthful, specific value. Do not force a decorative photo. + +Never assume an image found online is licensed for reuse. + +## Write the ImageBrief + +Specify the selection target before sourcing or ranking: + +```md +## ImageBrief +- Image job: +- Subject: +- Action / moment: +- Environment: +- Point of view: +- Emotion / state: +- Evidence boundary: +- Desired focal placement: +- Text-safe zone: +- Target crop(s): +- Brand cues: +- Must include: +- Must avoid: +``` + +Use observable direction. Replace “professional and engaging” with details such as “first-person view of a manager's notebook across from a teammate; open space in the upper left; laptop closed.” + +## Inspect candidates + +Inspect every candidate you rank. Do not infer the contents of an unopened file, URL, contact sheet, or unseen gallery. View important finalists at full size and at approximate feed-thumbnail size. + +Reject a candidate before scoring when it: + +- contradicts the content or implies unsupported proof, transformation, endorsement, or emotion; +- exposes private information, confidential UI, or an identifiable person without suitable permission; +- has unknown or unsuitable usage rights for the intended publication; +- is generic enough to fit unrelated content equally well; +- lacks one clear subject or loses the essential action at the target crop; +- is too small, blurred, watermarked, artifacted, or visibly malformed for the output; +- contains baked-in text or branding that conflicts with the cover; +- cannot leave usable space for the required copy, even with a crop, panel, or scrim. + +## Rank viable candidates + +Score each viable candidate 0–2 and apply the weights below. Use the score to make reasoning explicit, not to predict click-through rate. + +- **0:** absent, contradictory, misleading, or unusable. +- **1:** plausible but generic, inferred, weak at thumbnail size, or dependent on a repair. +- **2:** specific, immediately visible in the asset, and strong without needing an explanatory caption. + +| Dimension | Weight | Question | +| --- | ---: | --- | +| Promise relevance | ×3 | Does it visually support the exact promise? | +| Authenticity / proof fit | ×3 | Is the implied claim honest for this source mode? | +| Audience self-recognition | ×2 | Will the intended viewer recognize their situation or desire? | +| Focal stopping power | ×2 | Is there one immediately legible subject, contrast, or moment? | +| Thumbnail clarity | ×2 | Does the essential meaning survive at small size? | +| Text-safe composition | ×1 | Can the required copy sit clearly without hiding the subject? | +| Crop resilience | ×1 | Can it survive the target ratio and likely variants? | +| Brand fit | ×1 | Does it feel credible for this creator or brand? | + +Maximum: 30. Treat 24–30 as strong, 20–23 as usable with a clear fix, and below 20 as a signal to source again. Reject any candidate scoring 0 on promise relevance, authenticity, or thumbnail clarity regardless of total. Break ties in that order, then use focal stopping power. + +Show the per-dimension scores, not only a total. A common stock metaphor or visual cliché—generic handshake, generic meeting, floating product, anonymous smiling person—cannot receive 2 for promise relevance, self-recognition, or focal stopping power unless concrete details in the asset make it specific to this promise. Do not award specificity supplied only by the brief or cover text. + +## Plan the crop and treatment + +For the selected image, specify: + +- target aspect ratio and any size variants; +- focal point as approximate `x% / y%` within the original; +- essential region that must survive the crop; +- preferred text-safe zone and reading direction; +- whether a crop, blur, scrim, gradient, or solid panel is needed; +- whether the subject's gaze or motion helps lead toward the copy; +- fallback crop if platform UI or responsive variants cover the first choice. + +Never crop out the evidence that made the image relevant. Do not use heavy treatment to rescue an image whose subject or meaning is wrong. + +## Source when no candidate works + +Choose one primary next action: + +- **Capture brief:** give a shot list with subject, action, viewpoint, light, background, negative space, and avoid list. +- **Search queries:** describe content literally—subject + action + environment + point of view + composition. Provide 3–5 queries and require a license check. +- **Generation prompt:** describe the same concrete scene, composition, crop, negative space, and exclusions. Label the result as representative, not evidence. +- **Graphic fallback:** recommend a screenshot, artifact, diagram, or type-led cover when a photo would be decorative or misleading. + +Do not silently switch from real evidence to a generated substitute. + +## Deliver an ImageSelectionPack + +```md +## ImageSelectionPack +- Audience / promise: +- Image job: +- Source mode / provenance: +- Selected asset: +- Why it wins: +- Evidence boundary: +- Candidate ranking and rejection reasons: +- Target crop / focal point: +- Essential region: +- Text-safe zone: +- Recommended treatment: +- Rights / privacy status: +- Fallback asset or crop: +- Capture brief, search queries, or generation prompt if needed: +- Validation status: proposed / inspected / crop-previewed / rendered +``` + +Hand this pack to `design-marketing-cover`. Keep **proposed** separate from **inspected**: never claim thumbnail clarity, crop safety, resolution, or visual quality for an asset that has not actually been viewed. diff --git a/packages/core/skills/select-marketing-image/agents/openai.yaml b/packages/core/skills/select-marketing-image/agents/openai.yaml new file mode 100644 index 0000000..875131f --- /dev/null +++ b/packages/core/skills/select-marketing-image/agents/openai.yaml @@ -0,0 +1,4 @@ +interface: + display_name: "Select Marketing Image" + short_description: "Choose credible images that earn attention and fit the copy" + default_prompt: "Use $select-marketing-image to choose and crop the strongest image for my marketing content." diff --git a/packages/core/skills/select-marketing-image/references/xiaohongshu.md b/packages/core/skills/select-marketing-image/references/xiaohongshu.md new file mode 100644 index 0000000..c884388 --- /dev/null +++ b/packages/core/skills/select-marketing-image/references/xiaohongshu.md @@ -0,0 +1,31 @@ +# Xiaohongshu image-selection reference + +Use this reference for Xiaohongshu note covers. Treat these as creative heuristics, not guarantees about distribution. + +## Feed conditions + +- Default a portrait cover to 3:4, commonly 1080×1440, unless the publishing workflow specifies otherwise. +- Judge the candidate inside a small two-column-feed preview, not only at full resolution. +- Preserve the main subject, result, and essential gesture inside the target crop with room for short overlay copy. +- Keep important faces, hands, evidence, and text-safe regions away from likely crop edges and UI overlays. + +## Useful image jobs + +- **Contrast scene:** a real visual or social contrast that creates immediate tension. +- **Emotional close-up:** a genuine expression that is directly relevant to the note. +- **Visible outcome:** a source-supported result, artifact, or comparison. +- **First-person immersion:** hands, workspace, screen, environment, or an over-the-shoulder view that puts the reader inside the task. +- **Product in use:** the product solving the recognizable situation rather than floating as decoration. + +Prefer self-insertion over generic prettiness. The selected image should help the target reader think “this concerns me” before they read every word. + +## Source boundaries + +- Do not use stock or generated people as implied personal testimony. +- Do not fabricate before/after evidence or emotional reactions. +- Treat screenshots as evidence: preserve the relevant UI while removing private data. +- Use a type-led cover when no available image is both specific and truthful. + +## Series behavior + +When several posts belong to one series, keep the crop grammar, focal placement, light, or recurring environment recognizable. Test a different image hypothesis without changing every other cover variable at the same time. diff --git a/packages/core/skills/write-marketing-copy/SKILL.md b/packages/core/skills/write-marketing-copy/SKILL.md new file mode 100644 index 0000000..0a53e11 --- /dev/null +++ b/packages/core/skills/write-marketing-copy/SKILL.md @@ -0,0 +1,137 @@ +--- +name: write-marketing-copy +description: Turn rough source material into truthful, high-retention marketing copy for social posts, carousels, ads, launch graphics, and campaign content. Use when the user wants stronger hooks, titles, cover text, readable body copy, calls to action, shareable framing, Xiaohongshu copy, or a content package that OpenCanva can design. Also use before create-design when a graphic must win attention and sustain reading. +--- + +# Write marketing copy + +Convert the user's source into a content package that earns attention, keeps its promise, and is easy to lay out. Treat copy as a sequence—discovery, click, read-through, trust, then action—not as one undifferentiated paragraph. + +## Protect the promise + +- Preserve the source's facts, qualifications, and causal limits. +- Never invent results, testimonials, credentials, urgency, scarcity, or authority. +- Mark missing proof as a question or placeholder; do not silently fill it. +- Make the title and cover compelling by selecting a sharp truthful angle, not by overstating the content. +- Ensure every promise made before the click is paid off early in the body. + +## Build the brief + +Extract or infer these fields before writing: + +- **Audience:** who should immediately recognize themselves? +- **Current state:** what are they trying, feeling, fearing, or misunderstanding? +- **Desired change:** what useful outcome can this content honestly deliver? +- **Source truth:** which facts, examples, stories, and claims may be used? +- **Goal:** click, read, save, share, reply, sign up, or buy? +- **Channel:** Xiaohongshu, Instagram, LinkedIn, ad, landing graphic, or a generic social post? +- **Voice:** the user's natural tone, brand voice, or supplied reference samples. + +Ask only for a missing input that would materially change the result. Otherwise state a concise assumption and proceed. When the target is Xiaohongshu, read [references/xiaohongshu.md](references/xiaohongshu.md). + +## Choose one content angle + +Express the angle as: + +> For **[audience in a recognizable situation]**, show **[specific useful change]** through **[credible mechanism or proof]**, so they can **[action or identity payoff]**. + +Prefer an angle that scores well on: + +1. **Relevance** — the intended reader recognizes “this is for me.” +2. **Specificity** — the situation and payoff are concrete. +3. **Tension** — there is a gap, surprise, mistake, tradeoff, or unresolved question. +4. **Credibility** — the source contains enough proof to support it. +5. **Share motive** — sharing helps someone, signals identity, or gives language to a felt experience. + +Do not combine several weak promises. Pick one dominant promise and make the rest supporting points. + +## Write the discovery package + +Draft three meaningfully different candidates, then select one. Vary the mechanism, not just synonyms: + +- **Benefit:** state what the reader can gain. +- **Pain:** name a familiar costly problem. +- **Relief:** offer a simpler, faster, or less painful route without false ease. +- **Recognition:** articulate a feeling or situation the audience has not named clearly. +- **Contrarian:** challenge a familiar belief only when the body can prove the reversal. +- **Authority:** borrow a study, expert, or institution only when the source is verifiable and accurately represented. +- **Emotion:** lead with delight, frustration, fear, hope, or surprise without manipulating or shaming. + +For each candidate, write: + +- **Title:** carries topic, searchable language, and the main frame. +- **Cover copy:** creates immediate self-relevance and a reason to click. +- **Hook:** pays off the promise in the first lines instead of repeating the title. + +Do not make title and cover copy identical. Let them add information to each other while pointing to the same promise. + +## Structure for read-through + +Use the shortest structure that fully delivers the value: + +1. **Hook:** recognition, outcome, tension, or a concrete scene. +2. **Orientation:** tell the reader what they will get and why this source is worth their time. +3. **Value units:** one idea per paragraph, card, or carousel board; front-load the useful sentence. +4. **Proof:** example, demonstration, comparison, result, source, or clearly labeled personal experience. +5. **Payoff:** restate the change in practical terms. +6. **CTA:** request one natural next action that follows from the content. + +For a story, use **setup → obstacle → turn → change → transferable takeaway**. Include only details that increase understanding, emotion, or credibility. + +## Make the copy easy to read + +- Use short sentences and one idea per block. +- Replace abstractions with observable situations, actions, objects, and numbers from the source. +- Put the conclusion before the explanation when the reader needs the answer first. +- Use headings and lists as navigation, not decoration. +- Remove throat-clearing, duplicate claims, generic motivation, and empty superlatives. +- Preserve useful nuance, but move caveats next to the claim they qualify. +- Match the audience's language; prefer the words they search or say over industry jargon. + +## Keep a human voice + +When samples exist, extract recurring traits—sentence length, rhythm, vocabulary, stance, humor, and favorite transitions—then write with those constraints. Never imitate a living creator's distinctive style on request; use high-level traits to create an original voice. + +After drafting: + +- Replace stock AI transitions and perfectly symmetrical phrasing. +- Add only source-grounded observations, minor texture, and natural rhythm. +- Read aloud and simplify anything a person would not naturally say. +- Keep deliberate roughness subtle; clarity matters more than forced slang. + +## Deliver a ContentPack + +Return or maintain this compact handoff for `create-design` and `design-marketing-cover`: + +```md +## ContentPack +- Audience: +- Channel / goal: +- One-sentence promise: +- Selected angle: +- Title: +- Cover copy: +- Hook: +- Body / board outline: +- Proof available: +- CTA: +- Search phrases: +- Voice notes: +- Source boundaries / assumptions: +- Claims needing confirmation: +- Alternate title + cover pairs: +``` + +Then provide the publishable copy. Keep analysis outside the copy so the user can paste the finished text directly. + +## Final audit + +Confirm all of the following: + +- The intended reader can recognize relevance in two seconds. +- The title and cover make one clear, supported promise. +- The opening pays off that promise immediately. +- Each section advances the reader instead of restating the premise. +- Facts and proof trace back to the user's source. +- The CTA asks for one proportionate action. +- A reader has a concrete reason to save or share it. diff --git a/packages/core/skills/write-marketing-copy/agents/openai.yaml b/packages/core/skills/write-marketing-copy/agents/openai.yaml new file mode 100644 index 0000000..0933639 --- /dev/null +++ b/packages/core/skills/write-marketing-copy/agents/openai.yaml @@ -0,0 +1,4 @@ +interface: + display_name: "Write Marketing Copy" + short_description: "Turn source material into readable, clickable social copy" + default_prompt: "Use $write-marketing-copy to turn my source material into a high-retention social content package." diff --git a/packages/core/skills/write-marketing-copy/references/xiaohongshu.md b/packages/core/skills/write-marketing-copy/references/xiaohongshu.md new file mode 100644 index 0000000..72e7fa4 --- /dev/null +++ b/packages/core/skills/write-marketing-copy/references/xiaohongshu.md @@ -0,0 +1,36 @@ +# Xiaohongshu copy reference + +Use this reference only when Xiaohongshu is the target. Treat it as an editorial heuristic, not a guarantee about the platform algorithm. + +## Discovery and search + +- Write for both recommendation discovery and active search. +- Put the audience's natural search phrase in the title when it fits. Prefer “how to take better photos” language over specialist terminology such as “composition theory.” +- Mine the user's source, audience questions, comments, support requests, and reviews for real phrasing. Do not keyword-stuff. +- Let the title establish the topic and angle; let cover copy add relevance, benefit, or tension. + +## Useful title frames + +- Benefit: “A practical way to …” +- Pain: “If you keep getting stuck at …” +- Relief: “The lower-friction way I …” +- Recognition: “You are not bad at X; you may be missing Y.” +- Contrarian: “What looks like X may actually be Y.” +- Evidence: “What changed after …” + +Keep the title faithful to the note. Avoid absolute claims unless the source genuinely proves them. + +## Read-through + +- Deliver the promised answer in the opening lines. +- Keep paragraphs short enough to scan on a phone. +- Use one useful idea per paragraph or carousel board. +- Prefer concrete scenes, comparisons, checklists, and examples over generic advice. +- Close with one context-appropriate action: save for later, share with a specific person, answer a real question, or try one step. + +## Human voice + +- Build voice from the user's own samples when available. +- Use conversational wording without manufacturing slang. +- Vary rhythm and remove generic AI transitions. +- Never invent a personal story to create “authenticity.” diff --git a/packages/core/template/AGENTS.md b/packages/core/template/AGENTS.md index 942b121..3f8ea4a 100644 --- a/packages/core/template/AGENTS.md +++ b/packages/core/template/AGENTS.md @@ -16,7 +16,7 @@ npm run sync # re-copy the bundled agent skills — run after a fresh clone ## Authoring designs — read the skills first -The authoring know-how ships as **Agent Skills** under `.agents/skills/` (and `.claude/skills/`). Before writing or editing anything under `designs/`, read **`.agents/skills/canva-authoring/SKILL.md`** — it's the source of truth for the file contract, the object primitives, the coordinate system, the design tokens, and the inspector-compatibility rules. Use **`create-design`** to make a new graphic, **`create-theme`** for a new palette, **`apply-comments`** to process inspector markers, **`current-design`** to resolve "this design", **`svg-illustration`** before drawing any hand-authored SVG illustration. +The authoring know-how ships as **Agent Skills** under `.agents/skills/` (and `.claude/skills/`). Before writing or editing anything under `designs/`, read **`.agents/skills/canva-authoring/SKILL.md`** — it's the source of truth for the file contract, the object primitives, the coordinate system, the design tokens, and the inspector-compatibility rules. Use **`create-design`** to make a new graphic, **`write-marketing-copy`** to turn source material into a click/read/share content package, **`select-marketing-image`** to choose and crop the focal image, **`design-marketing-cover`** for cover composition, **`create-theme`** for a new palette, **`apply-comments`** to process inspector markers, **`current-design`** to resolve "this design", and **`svg-illustration`** before drawing any hand-authored SVG illustration. ## Hard rules (these break the editor silently if violated) diff --git a/packages/create-opencanva/README.md b/packages/create-opencanva/README.md index 4f8f95f..9cee84c 100644 --- a/packages/create-opencanva/README.md +++ b/packages/create-opencanva/README.md @@ -20,9 +20,10 @@ The scaffold drops a ready-to-run project into the target directory: - **`designs/start-here/`** — a starter design to open and learn from - **`opencanva.config.ts`** + **`tsconfig.json`** — preconfigured - **`AGENTS.md`** (+ a byte-identical `CLAUDE.md` copy) — the cross-tool repo guide -- **`.agents/skills/`** and **`.claude/skills/`** — the six authoring skills - (`canva-authoring`, `create-design`, `apply-comments`, `current-design`, - `create-theme`, `svg-illustration`) so Claude Code, Codex, Cursor, … can author for you out of the box +- **`.agents/skills/`** and **`.claude/skills/`** — the nine authoring skills + (`canva-authoring`, `create-design`, `write-marketing-copy`, `select-marketing-image`, + `design-marketing-cover`, `apply-comments`, `current-design`, `create-theme`, `svg-illustration`) so Claude Code, + Codex, Cursor, … can author marketing-ready graphics for you out of the box - **`@opencanva/core`** pinned as a dependency Then `npm install && npm run dev`, open , and load a design at `/d/`.