Master PPT
Master PPT generates static HTML horizontal page-turning PPTs. When using this skill, first organize the user's natural language requirements into a JSON plan, then call the local project generator to output index.html and assets/.
Version
Current version: 0.4.1
Each time you complete a user request and are about to prepare the final reply, run:
node <skill-root>/scripts/check_latest_version.mjs
If the script produces output, append the output at the end of the final reply to remind the user to update; if the script produces no output or the check fails, remain silent and do not mention the version check.
Skill Directory
The current directory where SKILL.md is located is the Skill root directory, referred to below as <skill-root>.
Built-in generator directory:
<skill-root>/project
Rendering script:
<skill-root>/scripts/render_goal_deck.sh
Version check script:
<skill-root>/scripts/check_latest_version.mjs
Safe rework script:
<skill-root>/project/scripts/revise-goal.mjs
Modes and Task Routing
- For each task, first determine whether it is
new(new creation) orrevise(rework). The user's explicit request in this session always takes priority. - If the user says "make one / create new / redo / make another / generate a PPT" and does not specify a locatable existing finished product or
goal.json, always enternew. Having made a PPT in historical conversations cannot be a reason to reuse an old draft. newis a permanently retained complete capability: each new creation creates an independent output directory, independentgoal.json, and an independent PPT; it must not become limited to only modifying old drafts because rework capability was added.- Only when the user clearly points out which existing PPT, which page, or which
goal.jsonto modify should you enterrevise. When the target is not unique, first locate it or ask, and do not arbitrarily treat the "latest one" as the target. - When the user provides a knowledge base, material directory, or reference files, only read content explicitly specified for this task and actually existing; do not guess local paths or apply business materials that were not provided.
Generation Principles
This Skill is a template orchestrator. The default goal is to quickly and stably fit user requirements into registered page components and output an HTML PPT that can be opened offline.
The default mode is "lock template, fill copy": retain the original visuals, structure, quantity, visibility, emphasis, color scheme, chart types, and image slots of the selected page components, and only replace visible text content. Unless the user explicitly requests adjusting page properties, do not change any non-copy props.
By default, do not perform visual refinement, do not make screenshot aesthetic judgments, and do not repeatedly rework because of ordinary line breaks or imperfect local layout. Only when the user explicitly requests "visual refinement," "100% inspection," or "help me adjust it until satisfied" should you enter the visual QA process.
Usage Rules
- Running the generator requires Node.js 20+ and npm; on first generation, the rendering script will install dependencies in the Skill's built-in
project/directory. - Style selection is a mandatory gate before
newmode generation: after understanding the theme, audience, tone, information density, and media needs of this task, first rank the 12 styles in the library for matching and choose the 9 most suitable; unless the user explicitly says "you decide the style too" or "skip style confirmation," you must not choose the final style on the user's behalf. Even if the user has already given a style preference, put that style at the top and ask the user to confirm.revisemode, reuse the original theme when only copy or data is changed; re-run the gate only when the user explicitly asks to change the style. - The matching of the 9 candidates must comprehensively consider content domain, target audience, level of formality/energy, data density, and image dependency, not just a single keyword match; rank them from highest to lowest suitability, and when tied, preserve effective differences in light/dark, serious, and energetic directions. Do not claim that the style library has only 9 sets; state that they are "9 intelligently matched from 12 sets."
- Use
node <skill-root>/project/scripts/build-theme-style-grid.mjs --themes <themeA,...,themeI> --out <current-workdir>/output/<deck-name>/theme-style-grid.pnggenerate this session's exclusive 3×3 nine-grid in ranking order. The user-visible reply must embed the image using the expanded absolute path, and list in the same order1-9ofthemeXX + 风格名 + 一句适配理由, mark the top-ranked "Top Recommendation," and ask the user to choose by number or style name. The nine-grid is only for display in the reply and must not be written intogoal.jsonor any media field. - After sending the nine-grid selection request, you must pause and wait for the user's reply; when
themePackis not selected, you must not creategoal.json, runlayout:query, generate media, or render the PPT. - Confirm two things before starting work: theme style and whether images/videos are needed. The theme style is confirmed according to the above nine-grid gate; when media requirements are unclear, also ask briefly. Only in environments where questions cannot be asked (scripts/batch processing), choose on your own, and list the top-ranked style and reason in the delivery notes.
- Delegation mode: when the user only says "you decide everything" or "no need to ask, just start" about the content or overall matter, still execute the nine-grid style gate; only when the user explicitly delegates the "final style" to the agent as well or explicitly asks to skip confirmation, directly choose the top-ranked theme. When the user only says the copy is "casual" or "make it up," only draft the content yourself; style, page count, media, and other provided items must not be changed without authorization.
- In non-interactive/one-off execution (when follow-up questions are impossible): if no style is specified, choose an accepted theme based on the content topic; when there are no real materials and images cannot be generated, prioritize media-free pages and do not call image-gen; explain all assumptions in the final notes.
- Deck language follows the user's communication language: for non-Chinese users, add at the top level of
goal.jsonAdd at the top level"language": "en"; write all copy fields in the target language, and overwrite all default Chinese copy built into the pages (including decorative fields such as "Thank you for reading" on the ending page), with no Chinese remaining. The editor UI language automatically follows the opener's system language and can be switched manually in the upper right corner, with no need to handle it during generation. - Delivery format: by default, deliver an editable PPTX while retaining the HTML preview source for further modification. When the user explicitly asks for only HTML, PDF, or images, deliver according to their request; the general new-PPT capability is not affected by this default.
- PPTX file: still generate HTML first and start the local preview service, then call the local HTTP export service; in the end, provide only the PPTX file path or download result.
- Currently available styles:
theme01soft neumorphic style,theme02neon purple-green style,theme03dark-light code style,theme04glass candy style,theme05spectrum chart style,theme06dark atlas style,theme07cool white research style,theme08black-gold lab style,theme09deep blue magazine style,theme10golden index style,theme11high-energy growth style,theme12sonic neon style. - Ordinary automatic selection does not choose
theme10; use it only when the user explicitly specifies it, or when it is strongly relevant to finance/investment index content and inspect confirms it can be filled. <!-- theme-choice-hints:start -->theme01Light neumorphism style | Suitable for: product introductions / corporate reports | Audience: startup teams / product managerstheme02Neon purple-green style | Suitable for: tech launch events / AI, autonomous driving, robotics themes | Audience: tech company founders / technical leadstheme03Light and dark code style | Suitable for: technical proposals / developer conferences | Audience: engineers / technical managerstheme04Glass candy style | Suitable for: youth-oriented brands / consumer products | Audience: brand teams / designerstheme05Spectrum chart style | Suitable for: data reports / market analysis | Audience: data analysts / consulting advisorstheme06Dark graph style | Suitable for: high-density data displays / strategic analysis | Audience: strategy teams / investorstheme07Cool white research style | Suitable for: research reports / white papers | Audience: research institutions / consulting teamstheme08Black-gold experimental style | Suitable for: high-end launches / brand proposals | Audience: high-end brands / creative directorstheme09Deep blue magazine style | Suitable for: brand stories / personality interviews | Audience: PR teams / media editorstheme10Golden index style | Suitable for: financial data / investment reports | Audience: investment institutions / financial analyststheme11High-energy growth style | Suitable for: growth retrospectives / business plans | Audience: entrepreneurs / growth teamstheme12Sonic neon style | Suitable for: music entertainment / trend events | Audience: entertainment brands / event planners <!-- theme-choice-hints:end -->
- Do not use old tokens, old themes, old media slots, old style branches, or old entrance animation controls.
- For page selection, first use
npm --prefix <skill-root>/project run layout:query -- --theme <themePack> --role <role> --limit 8; when media slots are needed, add--needs-media、--planned-images <n>、--provided-images <n>or--image-gen. The candidate order is randomized each time; choose any suitable one from them, and do not always use only the first item in the list. - If fields are unclear, or for objects/arrays/count, images/media: first run
npm --prefix <skill-root>/project run inspect:layout -- --compact <layout...>; to write objects, arrays, quantities, or image props: runprops:safe, and for the whole goal useprops:safe -- --goal <file> --write. - When piping the JSON from
layout:query/inspect:layoutto a program for parsing, switch tonode <skill-root>/project/scripts/layout-query.mjs/node <skill-root>/project/scripts/inspect-layout.mjs:npm run, which prints a lifecycle banner before stdout and pollutes the JSON. - For long decks: first use
npm --prefix <skill-root>/project run goal:scaffold -- --title <title> --goal <goal> --theme <themePack> --pages <n> --chunk-size 5 --out output/<deck-name>/goal.jsonto generate a unique layout skeleton andgoal.fill-plan.json, then fill in props in sections according tofillPlan. - Copy length and array counts: prefer writing according to
fillPlan.text[].maxChars、fillPlan.arrays[].visibleCount、fillPlan.arrays[].nestedArrays; thedisplay/metricfield should contain only short words, short phrases, or numbers. - For Html fields (such as
headlineHtml/quoteHtml), write copy using only<br>for line breaks and<b>/<em>for inline emphasis; free HTML such as<span>is prohibited; the<span class>in theme default values depends on the theme CSS and is only a placeholder, do not copy it.validate:goal-specwill block free HTML. - Visible array items must contain actual copy; trailing items hidden by count/visibility controls may retain the "Please enter text" placeholder.
- Use the native effects built into page components for element entrance animations.
- Page transition animations can be adjusted in the preview control panel.
- Decks delivered to users do not display style/theme switching options by default; style switching is retained only on internal debugging demo pages. When the user explicitly requests retaining theme switching, write
preview: {"themeSwitcher": true}at the top level of the goal. - Do not hand-write free HTML slides; every page delivered to users must write
layout+props。roleOnly allowed to assist in page selection during the draft stage; must be replaced with specificlayoutbefore rendering. - The first 5 pages of each theme set
themeXX_page001tothemeXX_page005are all cover candidates. A deck can only choose 1 page from the first 5 pages as the cover; do not use multiple cover pages at the same time; body pages are selected from page 6 onward. - Do not have duplicate page components in the same PPT set: the final
slides[].layoutmust be unique. When selecting pages, record the usedlayout; different content pages should switch to other candidates under the same theme, and do not reuse the same layout by changing the copy. - A deck delivered to users cannot only write
roleand then rely on the page's default copy. Unless the user explicitly wants the default demo, every page's visible content must be written withpropscopy corresponding to the user's topic. - Prefer to only write the copy fields exposed by
layout:query/inspect:layout. When a field is an object or array, fill the internal key according tofillPlanandpropShapes.copyKeyshas already expanded nested paths (such ascopy.quote、items[].label); fill directly according to the listed paths. inspect:layoutmarkscontentLocked: truepages whose body is fixed by the component and cannot be filled in via props: switch to a layout whose body can be filled in, or use it only when the user accepts its default body. Fill arrays with visible items according tofillPlan.arrays[].visibleCount;decorativeKeysis a decorative slot, do not fill it.- Do not modify page metadata, component source code, className, CSS, style fields, or the default visual structure to complete content filling. Only fill in content within
propsand page attributes explicitly requested by the user. - It is allowed to use the top-level
textto override visible text slots, but only for replacing text content. Do not start a browser in normal generation to batch-extract all page text slots; only do runtime slot extraction when the user explicitly requests "thoroughly clear all template default copy/proofread visible copy page by page". newmode prohibits reusing the existing oldoutput/or old HTML ingoal.json; each request must create a new output directory for this run and a new JSON plan for this run.revisemode must use the target file specified by the user, and first havegoal:revisegenerate a snapshot and change report; do not manually modify the targetgoal.jsonbefore the snapshot.- The output directory is written in the current session working directory; if the user explicitly specifies another directory, follow their requirement. Do not write to
<skill-root>/project/outputin any mode. - HTML delivery: for the preview address given to the user, only give
http://127.0.0.1:<port>/(do not give https or .local variants); local HTTP can export HTML/PDF/PPTX, while local HTML orfile://cannot export editable PPTX. Do not returntheme-preview. When generating in an Agent APP with its own browser (such as Codex), remind the user to open that address in the system browser before exporting PDF/PPTX. - PPTX delivery: call
/api/export-editable-pptx; in the end only give the PPTX file path or download result. - When there is no browser session, direct script calls, or the preview export interface returns 403/5xx: switch to
npm run export:pptx -- <deck>/ppt <out.pptx>(useexport:pdffor PDF) to directly produce the file, without needing to start a browser session first. - If default copy unrelated to the user's topic appears in the output body, such as AI Capital / investment and financing / SoundWave / sound wave / Key Metrics / Roadmap / End of Report, etc., the JSON must be rewritten and re-rendered; it cannot be delivered.
Media workflow
- For media fields, only write the slot of
mediaSlots[].canPresetMedia: true, according to that slot'spresetProp/fieldPathwrite path;goal.jsonOnly reference relative media paths within the deck; do not reference temporary directories, external absolute paths,file://or remote URLs. - For visual material tasks, first determine intent: when there is no image but visual material is needed, first ask whether to reserve image slots; when there is no real material and images cannot be generated, prioritize selecting pages without media. If the user provides a material library/material directory path, it is considered an intent to use images: select at least 2 pages with media slots and fill them with suitable material. If the material path is inaccessible, switch to pages without media and inform the user in the delivery notes; do not leave placeholder hint text within the page. When the user agrees to use
--planned-images <n>/--needs-media, when the user provides material use--provided-images <n>/--provided-media, when the user explicitly requests original visual images/image generation, in the Codex environment use image-gen to generate images and add--image-gen; when image generation is not explicitly requested, first ask the user.plannedImages/needsVisual/imageGenonly indicates page selection intent; unless the user explicitly chooses to reserve empty slots, real media paths must be written before delivery; do not deliver empty media slots or forged paths. - For the user's local images/videos, first run
npm --prefix <skill-root>/project run media:stage -- <deck-output-dir-or-ppt-dir> <media-file...>, use the returnedrelativepath; AVIF will be converted to a browser-usable format. image-gen output should also first land in this deck's directory. - After rendering, verify each image/video referenced by the goal:
ppt/<relative>exists and the HTML contains the filename; when missing, only supplement the finalppt/assetsand rerun validation. Each image/video material may be used at most once; after material is used up, leave the media slot empty or switch to a page without media slots; unless the user explicitly requests it, do not repeatedly fill the same material. - When image-gen needs to generate more than 2 independent images, use multiple subagents to generate in parallel; do not wait serially one by one; generate each image independently; do not use one collage/material board and then split it. Subagents are only used for image generation, not for topic selection, copywriting, page selection, or validation.
New workflow (must be retained)
As long as the task is determined to be new, this section must be fully executed. Even if the user says "make a new one following the previous style", only the style preference may be reused; the previous content,goal.json or output directory may not be reused.
- Distill the user's goal:
title、goal、audience、owner, page count, content focus, and final product format. When the user does not specify the page count, a normal long deck defaults to about 10 pages; when the user explicitly requests a single page, 1 page must be generated. - Execute the 3x3 style gate: rank matches for the 12 style sets, take the top 9, run
build-theme-style-grid.mjs, embed a 3x3 image in the user-visible reply and list 9 reasons, then pause and wait for selection. After the user selects, then setthemePackand generaterandomSeed, for example<主题>-<日期>-<3位随机词>, to ensure random page selection is reproducible. - Determine image intent: when there is no image but visual material is needed, first ask whether to reserve image slots; when the user provides local material, first
media:stage; when image generation is explicit, use image-gen. - Use
layout:queryto select candidates; for objects/arrays/count/image props useinspect:layout+props:safe. - Each page carries only one primary information role. For pages that cannot be safely covered, prioritize changing the layout; do not force it by modifying style fields.
- Write the JSON into this work directory's
output/<deck-name>/goal.json; when the user explicitly specifies another output directory, follow their requirement. Before rendering, runnpm --prefix <skill-root>/project run props:safe -- --goal <goal-file> --writeand goal spec validation.--writethen verify the output'slayoutChanges; if the replacement is not accepted, change it back and switch pages. - After filling the chart page with your own data, the in-page insight/reading/conclusion copy fields must be rewritten together based on the new data; do not retain the default conclusions.
- Run the rendering script to output
<deck-output-dir>/ppt/index.html; the script uses the generator built into the Skill; do not switch back to an external project directory. - After rendering, verify asset paths; if anything is missing, add the final
<deck-output-dir>/ppt/assets. - Confirm the script completes the
validate:swissandvalidate:goal-copyvalidations. - Run
node <skill-root>/scripts/check_latest_version.mjsfor a silent version check. - The render script starts a local HTTP preview service and outputs
http://127.0.0.1:<port>/; if you need to specify a port, setDASHI_PPT_PREVIEW_PORTbefore running the script (use ports in the 5200-5999 range; 4178/4300/4400 are reserved for the user and are unavailable). You may only use this preview service; you must not substitute a static server such aspython -m http.server、npx serve: static servers have no export or autosave interface. Under the preview service, edits are autosaved toindex.htmlitself;file://local files opened do not autosave and must be exported before delivery. - Reply according to the delivery format: by default call
/api/export-editable-pptxto deliver the editable PPTX file path and keep the HTML preview source; if the user explicitly wants HTML only, provide onlyhttp://127.0.0.1:<port>/.
Safe rework workflow
Use only when the user explicitly specifies an existing finished product, page, or goal.json . If you only receive "change it" but the target is not unique, locate the target first; do not mistakenly modify other PPTs.
- Record the target
goal.json, the corresponding output directory, and the user's requirements. If there is only a PPTX and nogoal.json/ HTML source from this Skill, do not pretend to be able to make a lossless minimal modification; explain that source files are needed, or handle it separately as an import-and-rebuild task. - Treat "everything else unchanged" as a hard constraint: by default lock the
themePack、pageCount、slidescount, per-pagelayout, per-pagerole, and all unnamed content. First write this change as a JSON Patch file, for example:
{
"note": "第 4 页标题改为年度重点项目,其余不变",
"changes": [
{"op": "replace", "path": "/slides/3/props/title", "value": "年度重点项目"}
]
}
- Execute
npm --prefix <skill-root>/project run goal:revise -- --goal <goal.json> --patch <patch.json>. The script saves a pre-change snapshot and change report underrevisions/in the target directory, and rejects structural modifications to theme, page count, whole pages, layout, and roles. - Only when the user explicitly requests changing the theme, page count, or layout is structural rework allowed. When changing themes, still first run the 9-grid style gate and wait for confirmation; after confirmation, use
--allow-structure, then recheck all layout and props contracts. - After rework, run
props:safe、validate:goal-specand render validation, and check thechangedPathsin the change report against the user's requirements item by item. If extra field changes appear, restore from the snapshot and regenerate a minimal patch. - When delivering, explain the modified target, the actual change path, and the snapshot location; new tasks still return to the "New workflow (must be preserved)" and must not continue to use this rework target.
Quality fixes and browser checks
Only rework in the following cases: render failure,validate:swiss failure,validate:goal-copy failure, obvious template copy in the output that does not belong to the user's topic, or the user clearly pointing out that a page's content has a problem.
By default, fix at most 2 rounds. If it still fails, explain the blocking reason and do not continue with unbounded attempts.
By default, do not open a browser, do not create a Chrome profile, and do not extract all text slots. Only do a single browser smoke check when you have modified the generator/preview template/export logic, when the user explicitly asks to check the page effect, or when the previous round had the problem of props being overwritten by default values after running.
The browser smoke check only confirms that the page can open, the page count is correct, and the first and last pages are not blank. Do not default to screenshot fine-tuning, and do not repeatedly revise drafts because of ordinary line-break issues.
Example command:
<skill-root>/scripts/render_goal_deck.sh \
output/client-review/goal.json \
output/client-review/ppt/index.html
JSON structure
{
"title": "美国 AI 融资调研",
"goal": "面向投资团队汇报 2024-2026 年美国 AI 大额融资结构、资本流向和后续判断",
"audience": "投资团队 / 产业研究团队",
"owner": "研究团队",
"randomSeed": "ai-funding-20260609-a7k",
"pageCount": 8,
"themePack": "theme01",
"slides": [
{"layout": "theme01_page001", "props": {"kicker": "融资调研 · VOL.01", "titleTop": "美国 AI", "titleBottom": "融资调研", "lead": "从资本体量、赛道结构和典型公司拆解本轮 AI 融资周期。"}},
{"layout": "theme01_page006", "props": {"kicker": "核心数字", "value": "970", "unit": "亿美元", "sub": "2024 年美国 AI 风险投资规模创历史新高。"}},
{"layout": "theme01_page010", "props": {"kicker": "# 研究方法", "title": "横纵分析法", "cn": "用时间维度和赛道维度交叉识别融资变化。"}},
{"layout": "theme01_page030", "props": {"kicker": "# 典型案例", "title": "里程碑 · 头部公司融资节奏"}},
{"layout": "theme01_page084", "props": {"kicker": "# 附录", "title": "数据来源与研究说明"}}
]
}
If slides is empty,pageCount is only suitable for temporary draft previews. Before user-facing delivery, it must be changed to a specific layout + corresponding props.
Page Role
role is only used for draft page selection; the final JSON must resolve to a specific layout. For role descriptions, see references/layout-roles.md; actual candidates are based on the layout:query output.
cover can only be selected from the first 5 pages of the current theme.image / media candidates are based on actual mediaSlots, not page title keywords. Dynamic background pages can use ambient as an atmosphere page or section page.
You can specify a page directly:
{"layout": "theme01_page030", "props": {"title": "典型案例"}}
Delivery Capabilities
Newly generated presentations use embedded OPPO Sans 4.0 as the heading and body font by default. The generated preview page supports page turning, opening the sidebar to edit text, replacing the global font by heading/body/monospace text categories, clicking any text to set a dedicated font or custom local font after turning off the global font switch, adjusting page props, replacing image/video media slots exposed by components, adjusting image slot width, height, and shape individually, switching page transition animations, and exporting HTML/PDF/PPTX. Global font, dedicated font, and image slot settings are written to deck state, and with the preview service they are automatically written back to HTML; when exporting editable PPTX, objects are generated according to the browser's final computed styles. User-facing delivered pages do not display page number identifiers, page turning guidance, dot navigation, or index hints at the bottom.
Page Property Contract
For ordinary generation, do not read layout-manifest.json. First use the candidate summary output by layout:query . Only when a more detailed contract is needed, use npm --prefix <skill-root>/project run inspect:layout -- --compact <layout...> to view the page contract:
copyKeys: copy/data fields that can be safely rewritten.copyBudgets: copy length budget;display/metricthat is too long will be blocked by the goal spec.propShapes:copyKeys/ the internal shape of array fields; when writing object fields such ascopy、cells、items、rows, use only the keys listed here.mediaSlots: fields for writing images/videos, count key, default count, and maximum count.countBindings: binding between count parameters and array fields.fillPlanFor numeric fields, seenumericBoundsto fill in numbers:enforced:falseis a hint, and real data may exceed it,enforced:truemust be followed,semantics:'normalized'fills a 0-1 ratio; for fixed-length nested arrays, seefixedLength/fixedLengthsand fill by index without trial and error.controlKeys: fields operable in the right panel, not a general content filling checklist; use only when the user explicitly requests adjusting page properties. By default, only fillcopyKeys, visible arrays, and real media slots.
Validation
- Before rendering, you must run
validate:goal-spec. - After output, you must run
validate:swiss. - After output, you must run
validate:goal-copy. - After modifying the display demo, run
npm run showcase:update。