agentleFS
ITSpecialist111ITSpecialist111/Copilot-Cowork-Skills/executive-report-design-system/SKILL.md

executive-report-design-system

Skill48 starsChanged 3 months agoMITView on GitHub

Produces multi-page, print-ready HTML executive reports in a fixed editorial design language that does not look machine-generated. Assembles pages from a closed catalogue of named components (hero statement, KPI row, bar list, inline SVG trend, compare strip, status grid, flow strip, numbered cards, prose, risk callout, pull quote, data table) against a frozen stylesheet and a validated JSON data document, so every report is visually identical in language whatever the subject. Output is a single self-contained file with no CDN, no server, no web fonts and no charting library, that prints to A4 landscape one sheet per page and runs from SharePoint, OneDrive or an email attachment. Figures animate up to their value on screen and snap to final on paper. Use when the user says "build an executive report", "quarterly business review", "QBR deck as a document", "board report", "exec summary", "multi-page HTML report", "printable report", "PDF-ready report", "management report", "monthly report pack", "make this look designed", "not another AI-looking report", "use the report design system", "report skill", "branded HTML report", "self-contained HTML report", "report with page numbers", "A4 landscape report", "turn this CSV into a report", "turn this spreadsheet into a report", or asks for a recurring report that must look identical every time. Do NOT use for slide decks (use the pptx skill), for Word documents (use the docx skill), for a live dashboard that reads changing data (build a SharePoint Framework web part instead), or for a single-page throwaway chart.

The file

We split this skill into the rules it gives an agent

10 rules. About 0 are common, 8 are distinctive, and 2 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈8

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 2

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Distinctive:

    Ask the seven interview questions below.

    line 66
  2. Very specific:

    Read the data. Decide which components tell the story, using the decision table in references/component-catalogue.md.

    line 67
  3. Distinctive:

    Only one of them changes per report.

    line 130
  4. Distinctive:

    Every page is a fixed A4 landscape box containing exactly three children:

    line 163
  5. Distinctive:

    Ask all seven. Do not guess, and do not proceed on assumptions:

    line 232
  6. Distinctive:

    If it does not validate, fix the JSON.

    line 254
  7. Distinctive:

    Write real final values into the markup.

    line 259
  8. Distinctive:

    Do not deliberate. Match the shape of the data:

    line 273
  9. Distinctive:

    If everything is emphasised, nothing is.

    line 293
  10. Very specific:

    Use grow on the last block so a page never ends in a void.

    line 312

≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

Executive Report Design System

Assemble multi-page HTML executive reports from a closed component catalogue and a frozen stylesheet, so that every report looks like a designer built the template and an analyst filled it in — never like a language model improvised a layout.

When to Use

  • User wants a recurring report (QBR, board pack, monthly review) that must look the same every time
  • User has data — a CSV, a spreadsheet, a set of figures — and needs it presented, not just tabulated
  • User needs a document that prints properly to A4 and survives being emailed or stored in SharePoint
  • User explicitly complains that AI-generated documents look generic
  • User wants a single self-contained file with no external dependencies

When NOT to Use

  • Slide deck → use the pptx skill
  • Word document or letter → use the docx skill
  • A live dashboard that re-reads changing data → build a SharePoint Framework web part
  • One quick chart with no narrative → answer inline instead
  • A report where the user wants to choose their own colours and layout — this skill is deliberately not configurable

Quick Start

User: "Build a Q3 executive summary from the attached CSV. Audience is the exec team; the headline is that we beat plan but delivery slipped."

Steps:

  1. Ask the seven interview questions below. Do not guess any of them.
  2. Read the data. Decide which components tell the story, using the decision table in references/component-catalogue.md.
  3. Build the JSON data document. Validate it: python scripts/validate_report.py report.json
  4. Render: copy assets/design-system.css into a <style> block and assets/motion.js into an inline <script>, then assemble pages from assets/component-snippets.md.
  5. Lint the output: python scripts/check_output.py report.html
  6. Fix anything the linter flags. Do not hand over a report that fails the lint.

The One Rule

You are not designing. You are assembling.

The design already exists, in assets/reference-report.html. Your job is to pick the right blocks from a fixed catalogue, fill them with the user's data, and emit the file. You do not get a vote on colour, type, spacing or layout.

If you find yourself writing a new CSS rule, you have gone wrong. Stop and pick a different component.


Why This Skill Exists — The Anti-Generic Problem

Left alone, a language model produces a recognisable house style: a centred hero, three or four identical cards with emoji, a purple-to-blue gradient, rounded corners everywhere, Inter at 16px, generous uniform padding, a Key Insights heading, bullet lists of three, and a footer saying Generated by AI.

Everybody has seen it. It reads as a template, and it quietly tells the reader that nobody spent any time on this. For an executive audience that is an own goal — the document undermines its own content.

This design system is opinionated in the specific ways a generic generator never is:

The generic instinctWhat this system does instead
Gradient hero, saturated brand colourWarm paper #F7F3EC, one restrained red, used sparingly
Big bold headline, 700 weightVery large, very light (300) headline — confidence, not shouting
Colour everywhereColour carries meaning only. Red means "look here" or "this is at risk"
Every card identicalA hierarchy: hero sentence, then KPIs, then evidence, then the ask
Emoji and icon chipsNo emoji, no icon fonts, anywhere, ever
Rounded 12–16px corners, big shadows4px radius, a 1px rule, a shadow you can barely see
Centred textLeft-aligned, ragged right, like a printed report
"Key Insights", "Overview", "Summary"Headings that state a finding
Three bullets of fillerA sentence that states the finding, then the number that proves it
Full-width scrolling pageFixed A4 pages. It is a document, not a web page

The full ban list, with rationale, is in references/anti-generic-rules.md. scripts/check_output.py enforces the mechanical parts of it.

The test: a reader should assume a designer made the template and an analyst filled it in. Nothing about the output should suggest a machine chose the layout.


How It Works

The three layers

Only one of them changes per report. This is what makes the output deterministic.

  STYLE          CSS custom properties. Four palette classes.        never changes
                 Set one on .page; every colour resolves through it.

  COMPONENTS     A closed catalogue of named blocks. The skill        never changes
                 picks which and in what order. It never invents one.

  DATA           A validated JSON document. Every value, every        changes per report
                 label, every block choice lives here.

Same JSON in, same HTML out. If a report needs regenerating six months later, the JSON reproduces it exactly.

The authoring pipeline

  START      Beautiful HTML example        assets/reference-report.html      once
  EXTRACT    Design read into tokens       assets/design-system.css          once
  CODIFY     Catalogue + rules             SKILL.md + references/            once
  ─────────────────────────────────────────────────────────────────────────────
  EVERY TIME User sends prompt + data      "build a Q3 QBR from this CSV"
  OUTPUT     Validated JSON document       scripts/validate_report.py
  RESULT     Self-contained HTML           scripts/check_output.py

The first three steps are already done — they are this package. In use, the whole interaction is a two-line prompt and a data file.

Page model

Every page is a fixed A4 landscape box containing exactly three children:

<section class="page palette-warm-paper" id="p3">
  <div class="page-head">
    <span class="wordmark">Contoso</span>
    <span class="page-meta">Q3 Executive Summary &middot; Exec Team</span>
  </div>

  <div class="page-body stack gap-lg">
    <!-- three to five components -->
  </div>

  <div class="page-foot">
    <span>Contoso &middot; Q3 executive summary</span>
    <span>Page <span class="pageno"></span> of 9</span>
  </div>
</section>

Content must fit. Nothing scrolls, nothing spills. If a page overflows, move a block to the next page — never shrink the type to make it fit.

Running heads and feet are real elements repeated on every page. This is deliberate and non-negotiable: @page margin boxes are still unsupported in Chromium, and position: fixed does not repeat per page outside Firefox. In-DOM is the only approach that prints identically in Edge, Chrome, Firefox and Safari. See references/pagination-rules.md before changing anything about printing.

Motion

Figures count up with an ease-out quint curve, bars sweep out, the trend line draws itself, and cards rise in with a short stagger, triggered per page as it scrolls into view. You do not write this and you do not configure it — just do not break it:

  • The engine reads the final text already in the HTML, replays the arrival, then writes the identical string back. Write real values into the markup: $1.9M, never a placeholder or a zero.
  • Prefixes and suffixes survive: $1.9M counts through $1.3M, 4/8 counts through 2/8, +18.4% keeps its sign and decimal.
  • Bar widths are authored inline (style="width:61%"). The engine parks them at zero and hands the value back.
  • prefers-reduced-motion is honoured, and everything snaps to final on beforeprint, so paper never catches a half-counted number.

Hard Constraints

These come from the report having to survive being emailed, stored in SharePoint, and opened on a machine with no internet.

ConstraintWhy
One file, everything inlineSurvives email, SharePoint, a USB stick
No CDN, no <script src>, no <link href>, no @import, no @font-faceLocked-down tenants block egress; SharePoint page CSP restricts script origins
System fonts onlyNo network call, and Segoe UI on Windows is the face the design was drawn in
Charts are inline SVG or CSSSheetJS and Chart.js are unavailable or blocked in the target environments
Inline <script> for animation only, never for dataThe report must be complete and correct with scripting off
A4 landscape, one .page per sheetIt is a document, not a web page

scripts/check_output.py verifies all of these mechanically.


Procedure

1. Interview

Ask all seven. Do not guess, and do not proceed on assumptions:

  1. What is the report, and who reads it?
  2. What period does it cover?
  3. What is the single most important finding? (this becomes the hero sentence)
  4. What are the three or four headline numbers?
  5. What decision, if any, do you need from the reader?
  6. Organisation name for the wordmark, and any classification label?
  7. Which palette? (default to palette-warm-paper)

2. Build the JSON

Against references/report.schema.json. Content, component choice and palette token only — no geometry, no hex colours, no pixel values. Those live in the frozen stylesheet, and keeping them out of the data is what prevents drift.

3. Validate

python scripts/validate_report.py report.json

If it does not validate, fix the JSON. Do not render around a validation failure.

4. Render

Copy the frozen blocks unaltered. Assemble pages from assets/component-snippets.md. Write real final values into the markup.

5. Lint

python scripts/check_output.py report.html

Fix everything it flags before handing over.


Choosing Components — The Decision Table

Do not deliberate. Match the shape of the data:

The data is…Use
One number that matters most.hero sentence, figure in .accent
Three or four headline metrics.kpi-row
A metric plus its change.kpi-card with .kpi-delta
Ranked categories.bar-list plus .legend
A time series.trend inside a .panel
This period against last.compare-strip
Named items with a state.status-grid
Rows the reader will interrogate.data-table in a .panel
A sequence of steps.flow-strip
Parallel concepts.numbered-cards
Things needing a decision.highlights
One urgent thing.risk-callout
Explanation, caveats, method.prose.cols-2
A memorable quotation.pull-quote

Emphasis is rationed. At most one .is-emphasis and one .risk-callout per page. If everything is emphasised, nothing is.

Full class inventory: references/component-catalogue.md.


Page Order

PageContentRequired?
1Cover — title, rule, meta rowYes
2Contents — printed, with page numbersYes for 6+ pages
3Executive summary — hero sentence, KPIs, one chartYes
4..nEvidence — performance, delivery, whatever the story needsYes
n+1Method and assumptions — how the figures were derivedStrongly recommended
n+2Section divider — full bleed, palette-deep-inkOnly for long reports
n+3..AppendixOptional

Give a page three to five components. Two looks thin; seven looks like a dashboard. Use grow on the last block so a page never ends in a void.


Writing the Words

The prose is half of why this does not look machine-made.

  • Headings state findings, not topics. Not "Delivery Status" but "Eight active initiatives, four fully on track".
  • The hero sentence is one sentence with two or three figures in .accent. It should survive being read aloud.
  • Captions earn their place. "10 deals closed" is useful. "Total revenue" under a card labelled Total Revenue is not.
  • Red captions mean risk. .kpi-note.is-alert for "2 at risk · 1 blocked". Never for good news.
  • British English. Optimise, prioritise, organisation.
  • No hedging. "Legal review has run eleven weeks", not "There may be some potential delays in the legal review process".
  • Numbers in prose match the cards exactly. Never restate a figure differently.

Files in This Package

FilePurpose
assets/design-system.cssThe frozen stylesheet. Copy verbatim.
assets/motion.jsThe frozen motion engine. Copy verbatim.
assets/reference-report.htmlThe visual target — nine finished pages, every component, all four palettes.
assets/component-snippets.mdCopy-paste HTML for every component.
references/component-catalogue.mdExhaustive class inventory and the decision table.
references/anti-generic-rules.mdThe ban list, with rationale.
references/pagination-rules.mdPrint CSS that actually works, and the myths that do not.
references/report.schema.jsonThe data contract.
references/example-report.jsonA worked instance.
scripts/validate_report.pyValidates a data document. Standard library only.
scripts/check_output.pyLints generated HTML against the hard constraints.

Troubleshooting

SymptomCauseFix
Content spills past the page footToo much on one pageMove a block to the next page. Never reduce the font size.
A blank page appears when printingbreak-after: page on the last pageEnsure .page:last-of-type { break-after: auto } is present — it is in the frozen CSS
Backgrounds print whiteBrowser is stripping backgroundsprint-color-adjust: exact must be present — it is in the frozen CSS
Numbers do not animateValues written as 0 or a placeholderWrite the real final value into the markup
Numbers animate to the wrong valueSomething rewrote the text after loadNothing may modify a figure after render; remove it
Page numbers all read the sameCSS counter reset in the wrong placebody { counter-reset: pageno } and .page { counter-increment: pageno }
Bars are invisible.bar-fill rendering as inlineIt must be display: block — it is in the frozen CSS
Report looks generic despite the systemComponents used decorativelyRe-read references/anti-generic-rules.md; check emphasis is rationed
Fonts look heavier than the referenceMachine has no Segoe UI LightExpected fallback. Arial has no 300 weight; the layout still holds

Self-Check Before Handing Over

  • python scripts/check_output.py report.html passes
  • Frozen CSS and JS copied unaltered; no CSS rule added, no class invented
  • Every page fits — nothing overflows past the running foot
  • Every page has head, body and foot; the page total is written in
  • Cover and executive summary present; contents page numbers correct
  • Every figure appears in the markup as its final text
  • Red used only for meaningful figures and genuine risk
  • Charts with more than one style have a legend
  • Headings state findings, not topics
  • Opens correctly with JavaScript disabled

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.