| name | consulting-deck-design |
| description | Use when generating a dense, professional consulting/government-style slide deck with @office-kit/pptx (McKinsey/BCG/METI-council-caliber — cover, section dividers, executive summary, exhibits, appendix). Invoked when the user asks for a "McKinsey-style", "consulting-grade", or "board deck" presentation, or says the output looks "too generic" / "too much like a template" / "still too simple / thin compared to the real thing". Covers the visual design system, the chart-authoring pitfalls that make output look amateurish, and the verification workflow — not just "use gradients". |
Consulting-grade deck design with @office-kit/pptx
A deck that is schema-valid and opens without repair is a correct deck. It is not
automatically a deck that reads as real consulting/government work. The gap between
"technically fine PowerPoint" and "looks like it came out of a real engagement" is
almost entirely in restraint: fewer decorative flourishes, fewer colors, more
whitespace, and text that states a conclusion instead of a topic — and in the
density of substantiation per exhibit (analysis columns, footnotes, superscript
citations) that a first pass tends to skip.
This skill is written from hands-on comparison against two real McKinsey
deliverables:
- Reference A — a Japanese METI advisory-council submission (cover, ~10
exhibits, appendix). Terse, internal-working-deck register: minimal chrome, no
rule under the headline, action-title-only.
- Reference B — a Japanese-language, 68-page public COVID-19 client briefing.
Richer, external-publication register: rule-under-headline as the default,
serif headlines, a letter-prefixed "governing thought" convention, four-column
exhibits, pull-quotes, chevron timelines, and a numbered TOC spine reused per
section.
Treat every rule below as "here's what we saw break (or land) when compared side by
side with the real thing," not a style preference. Where the two references
disagree (rule-under-headline being the clearest case), the section below says so
explicitly and gives a decision rule instead of picking one silently.
Before you start: get a reference if you can
If the user has (or can share) an actual example of the target firm's / client's
deck, read it first — page through every slide. A generic "corporate blue +
gold" palette invented from scratch reads as generic-corporate, not
McKinsey-specific. Real firm decks have surprisingly little color (near-monochrome
brand-blue family + semantic red/green), and surprisingly little decorative
flourish. If you don't have a reference, default to the palette in this skill
rather than picking your own "premium" colors — gold/orange reads as generic
luxury branding, not strategy consulting.
Visual language
Palette
Deep navy → bright blue, plus one teal accent. No gold. Semantic red (risk /
negative) and green (positive) are fine even inside an otherwise blue-monochrome
palette — real decks use them for exactly that purpose, but sparingly: across
68 pages of Reference B, red appears on exactly two slides (a legal-disclaimer
line and one "increasing" trend arrow) — it is not a general-purpose "bad news"
data color, it is reserved for the single most alarming signal on the page.
NAVY_DARK #0A1628 — darkest gradient stop, divider/cover/TOC background
NAVY #132A4D — solid navy for boxes (org-chart nodes, roadmap headers)
BLUE #1E4FFF — primary accent, gradient bright stop, "highlighted" data
TEAL #00B8D9 — secondary accent
ACCENT_LIGHT #5B9EFF — tertiary tint for a 4th KPI card / chart series
SLATE #7A8699 — neutral / "current state" / de-emphasized bars
PANEL_GRAY #E8E8E8 — light-gray secondary surface (see below)
RED #D64545 — reserved for risk/negative data points and disclaimers —
use on at most one exhibit per section, not as a
recurring category color
GREEN #2E9E6C — positive, recommended, upside
INK #111827 — headline / body text (not pure black)
MUTED #5B6673 — captions, footers, eyebrow labels
Three background modes, used deliberately
Both references converge on exactly three slide-background treatments, each with a
distinct job. Don't invent a fourth (e.g. a mid-blue panel) — it reads as
decoration rather than information hierarchy.
- White — the default surface for analytical/exhibit slides (charts, tables).
- Light gray (
PANEL_GRAY, distinctly lighter than white but clearly not
white) — a secondary "commentary" surface: right-margin "so what" columns,
contrast callout boxes, a full-panel implications sidebar. Never the primary
background of a whole deck section — it marks "supporting", not "main".
- Dark navy (
NAVY_DARK/NAVY) — cover, section dividers, the TOC/agenda
spine, "governing thought" framework slides, and (occasionally) a full
commentary sidebar instead of gray, when the slide wants more visual weight on
the takeaway than on the exhibit.
A two-panel slide (e.g. white exhibit + gray or navy sidebar) usually needs no
rule line at the seam at all — the hard color-block edge already reads as a
divider. Save rule lines for dividing regions that share the same background
(see below).
Cover and section-divider slides: gradient, not flat fill
Flat navy reads as a corporate template. A real cover uses a diagonal navy→blue
gradient across the full slide. In @office-kit/pptx:
const bg = addSlideShape(slide, {
preset: 'rect',
x: inches(0),
y: inches(0),
w: PAGE_W,
h: PAGE_H,
});
setShapeGradientFill(bg, {
stops: [
{ offset: 0, color: NAVY_DARK },
{ offset: 1, color: BLUE },
],
angleDeg: 15,
});
Layer white/light-blue title text on top, generous vertical whitespace (the title
block sits roughly at the vertical center, not crammed to the top).
Headlines: bold weight + size for hierarchy, and (usually) a rule underneath
Both references use a visibly different, heavier headline treatment than the
sans-serif body/bullets/table text beneath. setShapeRunFormat's font field
only sets the Latin typeface (<a:latin>); Japanese glyphs render through a
separate East Asian typeface (<a:ea>), settable per-run via the fontEastAsian
field:
setShapeRunFormat(headlineBox, 0, 0, {
font: 'Georgia',
fontEastAsian: 'Meiryo UI',
bold: true,
size: 19,
color: INK,
});
setShapeRunFormat(bodyBox, i, 0, { font: 'Arial', fontEastAsian: 'Meiryo UI', size: 13 });
Don't use a serif CJK typeface (e.g. 游明朝/Yu Mincho) for headlines, even
though the reference decks visually appear to use one. A first pass tried
exactly that — it matched the reference decks' look in a LibreOffice-rendered
preview, but read as visibly wrong once the user opened the actual file outside
the preview pipeline. Font substitution for CJK serif faces is inconsistent
across PowerPoint/Keynote/OS installations in a way Latin serif faces aren't;
Meiryo UI is the safe, universally-available choice. Carry the headline/body
typographic hierarchy through size and weight only — a bigger, bolder
fontEastAsian: 'Meiryo UI' headline next to a smaller, regular-weight
fontEastAsian: 'Meiryo UI' body reads as distinctly "headline" without the
CJK-serif risk. Latin-only display words (a "Contents" TOC spine word, an
English loanword like "Resolve" used as a chapter name) can still use a Latin
serif (font: 'Georgia') safely, since that risk is CJK-specific.
Rule-under-headline — decision rule. Reference A (terse internal deck) never
draws a rule under the title. Reference B (richer external deck) draws a
full-width thin horizontal rule directly beneath the headline on nearly every
content slide — it is the default there, not an exception. For a general-purpose
"McKinsey-caliber" deck, default to drawing the rule (addSlideLine full
content width, LINE color, ~0.75pt) — it's the more consistent convention across
the larger sample and it gives long decks a stronger sense of structure. Drop it
only for the terser register the user explicitly asked for, or on slides where a
hard color-block seam already does the dividing job (two-panel layouts, full-bleed
navy framework slides).
Letter-prefixed "governing thought" headlines. For a slide making one load-
bearing claim (the kind of exhibit a reader might photograph out of context),
prefix the headline with a single bold letter + colon in the accent blue,
sequenced A, B, C… across a chapter's exhibits (mirrors the pointColors palette
convention, not literal exam grades): "A: 東南アジア市場は今後5年間、国内の7倍の ペースで成長する見込み". On a white background render the letter in BLUE; on a
full-navy background render it the same white/light color as the rest of the
headline (a colored letter loses contrast and reads as an error, not an accent, on
a dark surface — this is a real inconsistency the reference deck itself
resolves that way, not an oversight to "fix"). Reserve the prefix for a chapter's
primary exhibits; supporting/detail slides in between keep a plain headline with
no letter.
If the deck is long enough to need running navigation, keep a small kicker label
above the headline (~9–10pt, gray, regular weight, unbolded) — a quiet wayfinding
aid, not a second headline.
Numbered TOC / running agenda spine
A distinctive, highly reusable archetype from Reference B: a narrow (~15% width)
white left strip carries a single word (e.g. "Contents") in bold serif, rotated
90° so it reads bottom-to-top like a book spine (setShapeTextBodyRotationDeg).
The remaining ~85% is a full-bleed dark-navy field holding one large bold serif
numeral per chapter (01, 02, 03…), each with a thin rule and a 1–2 line
label beneath it. The current chapter's numeral, rule, and label render in
bright accent blue / white; every other chapter renders in muted gray. Reuse this
exact slide once per chapter (only the "active" index changes) — this is the
"running roadmap" convention real long decks use to keep a 60–100-page document
navigable, and it reads as far more deliberate than a single static agenda slide
shown once.
Left-sidebar "framework" layout
For a slide whose entire point is one short, bold statement plus 3–4 supporting
bullets (e.g. "this strategic pillar," "this technology map"), use a dark
navy-gradient left rail (~28% width) carrying the bold white statement, with the
bullets in the light area to the right. This is a distinct, recognizable layout
from the header+body formula every other slide type uses — real decks reserve it
for framework/thesis slides specifically, not everything.
Multi-line text formatting gotcha: if the statement has embedded \n line
breaks, each line becomes its own paragraph — setShapeRunFormat(box, 0, 0, {...})
only formats paragraph 0. Loop over every paragraph index or the later lines fall
back to the text box's small default style while only the first line looks styled.
Multi-column exhibits with vertical rule dividers
Reference B's densest, most "real" pages are 3–4 column layouts separated by thin
vertical rule lines (addSlideLine, vertical, LINE color, ~0.5–0.75pt),
spanning the full content height. Common column contents: a chart flanked by two
text commentary columns; four icon-badge + header + body columns (e.g. a
"5 R's"-style framework); or a bulleted list column beside a pull-quote column.
This is a different device from the single right-margin analysis column already
in this skill (still valid, still the right call for a plain chart-plus-commentary
slide) — reach for the multi-column-with-rules version when a slide has 3+
genuinely parallel blocks to show side by side, not just one exhibit plus one
comment.
Pull-quote blocks
A quotation callout: a small circular badge (solid NAVY fill) containing a
large bold quotation-mark glyph (" / ", U+201C/U+201D, oversized ~20–24pt,
white or PANEL_GRAY), positioned above or beside 1–2 sentences of quoted text,
followed by a bold attribution line introduced with an em-dash
(— 氏名、肩書き). Use for a single expert-quote moment per section, not on every
slide.
Icon strategy (no custom vector art)
Real decks use simple monochrome line-art pictograms (a person, a chart, a
lightbulb, a shield). @office-kit/pptx has no custom-path/freeform-geometry authoring API
and no bundled icon set, so don't attempt hand-drawn vector icons — the
practical, reliable substitute is a colored circle or rounded-rect "badge"
(addSlideShape ellipse/roundRect) containing a single safe glyph character,
centered, sized large (~18–24pt). Stick to Latin-1/general-punctuation glyphs —
multi-byte emoji/pictograph ranges are the same CJK-tofu-box risk this skill
already warns about for text, since LibreOffice/PowerPoint font substitution for
emoji is inconsistent across renderers.
growth / increase ▲ or ↑ decrease / decline ▼ or ↓
success / on-track ✓ risk / off-track ! or ✗
insight / idea ★ direction / next step →
process step N a filled circle badge with the bold numeral itself
quote " / " (U+201C / U+201D), oversized
Badge + glyph + header + body is one composite — groupShapes it, same as a KPI
card.
Chart technique: highlight one, gray the rest
The single most-repeated chart device across Reference B: a bar/column series
where one category is the narrative subject (bright BLUE) and every other
category is a neutral, de-emphasized fill (SLATE or a light gray) — not a
categorical rainbow palette. This is authored the same way the pie/doughnut
per-slice override already in this skill works: pointColors is a general
series-level field, not restricted to pie/doughnut —
series: [
{
name: '人口100万人当たりの死者数',
values,
pointColors: categories.map((c) => (c === 'スウェーデン' ? BLUE : SLATE)),
},
];
Reserve a full multi-hue categorical palette for charts where every category is
equally the subject (e.g. a segment-share pie); use highlight-one-gray-rest when
the slide's headline names a single subject ("A: スウェーデンは…").
Small provenance tags
Real exhibits mark themselves "非網羅的" ("non-exhaustive") or "例示"
("illustrative") in a small bordered tag in the corner when the chart/table isn't
meant to be a complete list — a plain bordered rect + 8.5pt text in the corner,
not a big banner. Add this to competitive-landscape maps, case-study callouts,
and anything else that is deliberately a sample rather than an exhaustive list.
Chart authoring — the mistakes that make output look amateurish
These are the actual defects a first pass produces; each one reads as "AI-generated
template" rather than "hand-built exhibit."
1. Pie/doughnut charts need explicit per-slice colors
varyColors: true (or @office-kit/pptx's default on pie/doughnut, which already sets it)
only requests that the renderer assign distinct colors per slice. It does not
guarantee every viewer actually cycles through a palette — some render every slice
in the same single color, which makes the chart useless. Always pass explicit
pointColors cycling through your accent palette:
series: [{ ...series[0], pointColors: categories.map((_, i) => PALETTE[i % PALETTE.length]) }];
2. Every multi-series or pie/doughnut chart needs a visible legend
ChartSpec.legend is undefined by default (no legend authored at all) — @office-kit/pptx
doesn't add one automatically. Without it, a reader can't tell which color means
which series/category. Add legend: { position: 'r' } to any chart with more than
one series, or any pie/doughnut (where "categories" function like series). A
single-series bar/line chart can skip the legend — its category-axis labels already
say what each bar/point is, and a legend there is redundant chrome.
3. Never plot two series with mismatched scales on one axis
Revenue in the hundreds and a margin percentage in single digits on the same axis
means the percentage line collapses to a flat line near zero — unreadable.
@office-kit/pptx's ChartSpec has no secondary axis. Don't try to fake one. Split into two
independent single-metric charts side by side instead — same slide, same story, each
chart properly scaled.
4. Don't overlay hand-drawn annotations on top of a native chart
It's tempting to draw dashed reference lines / inline value labels directly on a
chart (mimicking real decks that mark "2030 (48%)" right on the plot). Don't try
to compute the plot area's pixel position and overlay shapes on it. A chart's
internal plot rectangle is inset by however much room its own axis labels, legend,
and title need — that inset is decided by the rendering engine (PowerPoint /
LibreOffice / Keynote all differ) and isn't knowable at authoring time. An overlay
aimed at "where category index 3 should be" will drift out of alignment, sometimes
badly (labels landing on top of the y-axis, or off the right edge past the legend).
Instead, put the annotation beside the chart, not on it: chart on the left
~68% of the slide width, a right-margin column of 2–4 substantive "so what"
sentences (one per paragraph, a thin colored accent bar to its left) on the
remaining ~28%. This is what both reference decks' own market-growth exhibits
actually do — the "annotations on the chart" look you're copying is itself mostly
a right-margin (or multi-column) text block, not a plot overlay.
Footnotes and source citations
Real exhibits substantiate every number, and keep two conventions visually
separate rather than merging them into one line:
- Numbered footnotes (methodology/assumption notes): a small gray numbered
list ("1.", "2."…) at the bottom of the slide, each tied to a superscript
digit placed inline at the exact claim it qualifies — in a headline, an axis
label, or mid-bullet (e.g.
"投資回収期間が18ヶ月と最も短く¹"). Since the
simple text-authoring API is one run per paragraph (no supported way to mix a
normal-weight run and a superscript run within a single paragraph), use the
literal Unicode superscript digit characters (¹ ² ³ U+00B9/U+00B2/U+00B3,
⁴ ⁵ ⁶… U+2074+) typed directly into the paragraph text — they render as
normal glyphs in any font, no run-splitting required, and read as true
superscript footnote markers.
- Source line: a separate line beginning
資料: (or Source:), listing
citations comma-separated. Don't invent per-word hyperlink styling (blue +
underline on only some words in the line) — that needs multiple differently-
formatted runs in one paragraph, which the authoring API doesn't support.
Style the whole line uniformly instead: either plain MUTED gray (the more
common convention — most citation lines in both references are plain, not
hyperlinked) or, if you want the "clickable source" look, the whole line in a
muted blue with underline.
Every chart/table exhibit should carry at least a source line; add the numbered-
footnote block whenever a number depends on a stated assumption (survey sample
size, calculation basis, exchange-rate assumption) — this is what separates a
"real" exhibit from a bare chart. See "Composition and structure" below for how
this pairs with a right-margin/multi-column analysis block.
Composition and structure
- Group composite elements. A KPI card (rounded rect + accent tab + big number
- label), a roadmap node (header bar + numbered badge + title), or an icon
badge (circle + glyph + header + body) should be one
groupShapes unit, not
four independent shapes a future edit could misalign.
- A real deck's shape: cover → confidentiality/handling notice → agenda (as a
reusable numbered TOC spine, not a single static list) → executive summary
(headline finding, KPI dashboard, 3-pillar recommendation, financial-impact
chart, roadmap preview) → numbered sections, each opening on a divider slide (or
the TOC spine with that chapter active) → appendix (detailed tables, glossary,
sources, disclaimers) → closing. Long decks (60–100+ slides) are normal for a
real internal working deck; don't compress everything onto 10 slides just
because a reference example you saw was short — that one may have been a
client-facing extract, not the full working deck.
- Every exhibit earns its slide. A chart or table is never left to speak for
itself: pair it with a right-margin or multi-column analysis block (2–4
substantive, numbers-backed sentences — not generic filler) and a footnote/
source line. A slide with only a bare chart and a one-line caption reads as a
first draft, not a finished exhibit — information density (not clutter) is
what makes a page look like it came from a real engagement.
- Dense but not cluttered: 3–5 bullets per slide, one action title, one
exhibit (or one coherent multi-column composition). If you have two unrelated
exhibits worth showing, that's two slides, not one crowded slide.
Content craft: what actually reads as AI-generated
Everything above gets the visual language right. A visually correct deck can
still read as AI-generated on close inspection — the tell moves from the
layout to the content. This section is written from a real feedback loop:
a generated ~100-slide deck was run through an AI-content detector across
several rounds, and each round's fix sometimes introduced a new tell of a
different flavor. Treat "sounding human" as an ongoing discipline applied
while drafting, not a find-and-replace pass done at the end.
Numeric self-consistency is the single strongest signal
The #1 thing that got a deck flagged as AI-generated was a hard arithmetic
contradiction: one slide stated a 2030 target as a "+340億円 increment," a
different slide's scenario chart showed the same year's base case as an
absolute "900億円." Neither reading reconciled with the deck's own bridge
chart or P&L table. A systematic audit afterward found this wasn't an
isolated typo — the same headline figure had four different values across
different slides, a segment's contribution to profit had three, an NPV
total didn't equal the sum of its own stated parts, and a stated current-state
margin didn't match the P&L table's own baseline.
This happens naturally when slide content is drafted slide-by-slide — each
slide's numbers are locally plausible at the time they're written, and no one
slide is "wrong" in isolation. The fix is structural, not editorial:
- Before writing any slide content, build one explicit numeric model
(a plain object/constants block in the generator script) covering every
quantity that will appear on more than one slide: the P&L path (revenue,
gross profit, SG&A, operating profit per year), the pillar/segment
contribution breakdown, scenario spreads, cash-flow figures.
- Add a self-check that runs when the script executes — e.g. assert
grossProfit[i] - sga[i] === operatingProfit[i] for every year, and
baseline + sum(pillarContributions[i]) === operatingProfit[i]. Throw if
it doesn't hold. This turns "did I introduce a contradiction" from a
manual audit into something the generator itself refuses to produce.
- Derive every slide's numbers from that one model, never re-typed
per-slide. Decide once whether a headline figure is an increment or an
absolute, and never let a different slide imply the other reading.
- When two slides describe "the same" figure from different angles (a
segment's standalone P&L vs. its consolidated contribution to a synergy
bridge; a survey-based scenario vs. a sensitivity-table increment), either
make them equal or add a one-line footnote naming why they differ
(overhead allocation, scope difference). An unexplained gap reads as an
error even when the underlying reason is legitimate.
Source citations: vary the format, don't invent a fictional institute
A first-pass fix for "sources are too vague" (bare 資料: 部署名 on every
slide) overcorrected into "sources are suspiciously precise" — a uniform
部署名『Report Title』(Rev.X.X, 2026年M月D日確定版) template repeated on
40+ slides is itself an AI tell, just a different one. Two concrete fixes:
- Deliberately vary format and completeness. Not every citation needs a
title + version number + date. Mix in plain department names, a bare
"業界レポートによる" with no further detail, an occasional named person
instead of a department, and the fully-dressed form — in whatever
proportion feels like it was assembled by different people at different
times, because in a real deck it was.
- For external market/industry data, cite real research firms and real
government bodies (Euromonitor, GfK, Kantar, IMF World Economic Outlook,
a country's actual investment-promotion agency) rather than inventing a
plausible-sounding fictional institute (an early draft invented "ARERI —
アジア流通経済研究所," which read as exactly the kind of too-convenient
acronym an LLM fabricates). For a fictional company's internal citations
(hearings, internal working papers), attributing to the company's own
already-established departments is fine and doesn't have this problem —
the risk is specifically inventing a third-party organization that
sounds real but isn't.
Anonymized examples/case studies should not be structurally uniform
If a deck includes 2–3 anonymized case studies, giving every one of them the
same shape (tidy quote + clean lesson + fully-resolved success) reads as
templated — real case libraries are uneven. Deliberately vary: give one case
a direct quote and a resolved happy ending, give another just data with no
quote, and consider making one case an ongoing/unresolved situation
("current state: improving but still below target") rather than a clean win.
The variation in depth and resolution is itself what makes each one read as
independently researched rather than generated from one template.
Phrasing diversity is a moving target, not a one-time fix
Repeating the same closing-clause formula across many slides (〜が急務で ある, 〜が鍵となる, 〜を実現する, 〜見込みである, defaulting to 最も
as the only superlative device) reads as LLM-typical vocabulary. The trap:
fixing this by mechanically swapping in a different replacement phrase
(という計算になる, という結果が出ている, を起点とする) just creates a
new repeated tic once that replacement itself gets reused across a dozen
slides. There is no phrase that's safe to reach for by default every time —
the actual fix is sentence-level variety: sometimes state the number and stop
without a closing hedge at all, sometimes lead with the comparison
(A社の1.6倍) instead of a verb-based conclusion, sometimes invert
subject/verb order. If you're generating enough content that you can search
your own script afterward for any phrase appearing 4+ times, do that search —
but don't pre-emptively adopt a "safe" replacement vocabulary, since that's
exactly how the previous tic got created.
Verification workflow — do not skip this
- XSD schema validation on every generated slide/chart XML (see this repo's
test/lib/expect-schema-valid.ts pattern) — catches structural corruption.
- Render with a real engine and look at it. @office-kit/pptx's own bundled preview
renderer does not ship CJK fonts — Japanese (or other non-Latin) text renders as
tofu boxes in it even when the underlying XML is completely correct. That is a
preview-renderer limitation, not a bug in your output, but it means you cannot
trust the bundled preview for a CJK deck. Convert with a real office suite and
look at actual pages before calling the deck done:
soffice --headless --convert-to pdf --outdir /tmp/out deck.pptx
pdftoppm -png -r 150 -f <page> -l <page> /tmp/out/deck.pdf /tmp/out/page
Then view the PNG. Do this for at least one slide of every distinct archetype
you built (cover, divider, TOC spine, chart, pie chart, table, matrix, sidebar
layout, multi-column exhibit, pull-quote) — each is a different rendering code
path and bugs are archetype-specific (e.g. a legend bug affects every pie chart
but not a single-series bar chart; a footer-position bug affects every
sidebar-layout slide but not plain content slides).
- Read what you rendered critically, the way the user will: does the pie
chart's legend actually list distinct colors? Does the multi-line sidebar title
render at a consistent size on every line? Is the "annotation" text actually
next to the chart, not drifted onto the axis? Does a two-line footnote block
fit inside the slide bounds, or does the second line clip off the bottom edge?
Fix what you find and re-render — don't ship the first render un-inspected.