| name | blog |
| description | Create long-form technical articles as standalone HTML files with clean typography, responsive design, and inline SVG diagrams. Optimized for blog posts, technical write-ups, and documentation. Light theme, mobile-friendly, copy-paste safe for rich-text editors. |
| license | MIT |
| metadata | {"version":"1.0","author":"James Xu"} |
Editorial Article
Create technical blog posts and long-form articles as self-contained HTML files with editorial-quality typography and responsive design.
⚠️ ALWAYS Write in English
All articles must be written in English regardless of the language used in the user's request, source material, or SQL identifiers. This is a hard requirement — never switch to another language even if the user writes their prompt in Chinese or another language.
⚠️ NEVER Reveal Internal Query Shape or Business Logic
When the source material involves production queries:
- Do not describe the query shape in detail. Do not name the number of GROUP BY columns, the column names, the join type, or the table structure. These details can reveal classified system architecture or business logic.
- Use only vague characteristics. Acceptable: "a high-cardinality GROUP BY key", "a low-cardinality column with skewed distribution", "a many-dimensional aggregation". Not acceptable: "groups by nine columns representing X, Y, Z".
- Do not name the business domain beyond what is strictly necessary to explain the technical point. If the domain is irrelevant to the performance analysis, omit it entirely.
- This applies to all identifiers: column names, table names, partition values, business entity types, and any description that would let a reader infer the schema or data model.
⚠️ NEVER Use Real Table Names or Sensitive Identifiers
When the source material contains production SQL with real table names, column names, or business-specific identifiers:
- Always anonymize. Replace real table names with TPCH table names. Do not include any real production table names, column names, or business-specific identifiers in the article.
- Keep the SQL pattern intact. The query structure, join type, and predicate logic must be preserved — only the identifiers change.
- Be consistent. Once you choose an anonymized name, use it throughout the entire article including prose, code blocks, SVG labels, and captions.
- This applies to everything: SQL examples, log excerpts, plan trees, SVG diagram text, and body paragraphs.
Never mix anonymized and real names in the same article.
⚠️ ALWAYS Check the Correct Template First
Before writing any article, read the template for the selected style. The templates contain the authoritative CSS rules (exact values for padding, margins, colors, breakpoints) that must be reproduced verbatim.
- Coral style → read
assets/template.html
- Academic style → read
assets/template-academic.html
The prose descriptions in this file are a summary — the template is the spec. Do not rely on prose interpretation alone for styling decisions.
Style Selection
The /blog skill supports two visual styles. Determine which one to use before generating any output.
Detect from user request
If the user's request contains any of these keywords, use the corresponding style:
- Academic: "academic", "serif", "editorial", "journal", "paper", "Palatino", "longform", "essay"
- Coral: "coral", "modern", "tech", "default", "badge"
Ask when unclear
If no style keyword is detected in the user's request, call AskUserQuestion with:
- Academic — editorial journal style with serif typography (Palatino), plain bold headers, 720px wide. Best for long-form essays, deep-dive analyses, and paper-style write-ups.
- Coral — modern tech-blog style with coral section badges, sans-serif typography, 840px wide, light theme. Best for tutorials, explainers, and technical documentation.
Default to academic if the user skips the question or the response is ambiguous.
Apply the chosen style
Once the style is determined, read the corresponding template file and reproduce its CSS values exactly. Both templates share the same HTML structure (H1 + lede, H2 + divider, H3, code blocks, tables, figures), but differ in typography, colors, spacing, and header treatment.
When to Use
Use when the user asks to create:
- Technical blog posts
- Long-form articles or write-ups
- Documentation with narrative structure
- Tutorial or explainer content
- Any HTML article with multiple sections, code blocks, tables, and diagrams
- Cover images for blog posts ("generate cover image", "cover image for this article")
Don't use for:
- Diagrams only → use diagram-design skill
- Presentations → use pptx-generator skill
- Quick HTML snippets or components → use frontend-design skill
Design Principles
Typography hierarchy
- H1: 2.2em, bold, tight letter-spacing — one per article
- H2: 1.35em, bold, white text on coral background with rounded corners — section headers
- H3: 1.15em, semi-bold — subsection headers
- Body: 16px base, 1.72 line-height — optimized for reading
- Code: monospace, light gray background, slightly smaller (0.9em inline, 0.88em blocks)
- Lede: 1.12em, muted color — opening paragraph after title
Color palette (warm, readable)
--bg: #ffffff;
--fg: #1f2937;
--muted: #6b7280;
--accent: #2563eb;
--code-bg: #f6f8fa;
--border: #e5e7eb;
Section headers use a coral accent (#f97066) with white text for visual hierarchy.
Spacing & rhythm
- Container: max-width 840px, centered
- Vertical spacing: 56px top padding, generous margins between sections
- Section dividers: 2px solid coral bar below each H2
- Callouts: left border (3px) + tinted background, rounded corners
Mobile responsiveness
All articles include comprehensive mobile media queries:
- Scaled-down typography (h1: 1.6em, h2: 1.15em on mobile)
- Reduced padding (36px/16px vs 56px/24px)
- Tighter vertical spacing
- Horizontally scrollable tables (
.table-wrap container)
- Smaller code blocks (0.82em font, 12px/14px padding)
- Tightened list indentation (20px vs 24px)
SVG diagram integration
- Inline SVG with
viewBox only (no width/height attributes for editor portability)
max-width: 100%; height: auto; display: block; margin: 0 auto;
- Wrapped in
<figure> with <figcaption> for context
- Use
<polygon> for arrowheads (not <marker> — renders as squares in some editors)
- Avoid
<tspan baseline-shift="sub"> — breaks copy-paste to rich-text editors
- See global CLAUDE.md "SVG Diagrams" section for detailed conventions
Text overflow prevention:
- SVG text does not wrap automatically. Long labels inside boxes will overflow the box border and may be truncated at the viewBox edge.
- Use separate
<text> elements with distinct y coordinates for multi-line text inside boxes, and increase the box height to accommodate all lines. Avoid <tspan> — it works in browsers but gets stripped by some rich-text editors (e.g., WeChat), which dumps the raw text outside the SVG.
- Keep box content short. Move explanatory context into
<figcaption> or surrounding prose. For plan trees, put stage names (e.g., "Final Aggregate") as a <text> label above the box, and keep only the expressions inside the box.
- Place annotations inside the relevant box as a small bordered badge rather than floating text near the viewBox edge. Floating labels can be truncated even with
text-anchor="end" because glyph rendering extends past the anchor point.
- Text descenders overflow the baseline. In SVG, letters like
g, p, j extend below the text baseline. The visual bottom of a line is roughly y + 0.2 * font-size. Always leave at least 3–4px of padding between the text baseline and the bottom edge of its containing box.
- Always verify: check that the rightmost text pixel is comfortably inside the viewBox, not at
x = viewBox_width.
Spark UI Diagrams
When an article needs to illustrate Spark job behavior — stage metrics, SQL plan nodes, AQE statistics — reproduce the Spark UI's visual language exactly rather than inventing a custom style. Readers who use Spark daily will orient immediately.
A "Spark UI diagram" refers to either of two distinct SVG types:
- Stage List Table — a tabular mockup of the Spark UI Stages tab showing stage rows with metrics (Duration, Shuffle Write, Spill). Best for comparing across stages or highlighting anomalous task behavior.
- Plan Tree Diagram — a node-and-arrow diagram in the Spark UI SQL tab style showing operator nodes (Scan, Exchange, HashAggregate, etc.) wrapped in stage boxes. Best for explaining data flow through plan operators.
Stage List Table
Use a wide (680px viewBox) SVG table that matches the Spark UI's stage list. Keep it at full column width — these tables are dense with columns and need the space. The format established and validated in practice:
- Column layout: 6 columns — Stage, Description, Tasks, Duration, Shuffle Write, Spill (disk)
- Column positions (viewBox 680px wide): Stage at x=12, Description at x=80, Tasks at x=310, Duration at x=370, Shuffle Write at x=450, Spill at x=560
- Header bar:
fill="#333", white bold text, rx="6" on the outer rect with a square-bottom patch to flatten the bottom corners
- Column header row:
fill="#ececec", bold #555 text, font-size 11
- Normal rows: alternating
fill="#fff" / fill="#f6f6f6", plain #333 text, font-size 12
- Anomalous rows:
fill="#fff8f0" background, left accent bar (width="4", fill="#c0392b"), key metrics in bold #c0392b
- Sub-metric line: font-size 10,
fill="#888", same left padding, on a second y within the same row height
- Observation callout row: italic
fill="#555" text at font-size 11, after the last data row, summarizing why the stage is problematic
- Stage naming for co-located operators: when a join and partial aggregate run in the same stage, name them as
SortMergeJoin + HashAggregate (Partial) in the Description column and show their sub-descriptions on separate sub-metric lines
SQL plan node diagram
Reproduce the Spark UI SQL plan diagram style for Exchange, AQEShuffleRead, and similar nodes:
- Box:
fill="#c8e6f5", stroke="#7bbedd", stroke-width="1.5", rx="10"
- Header band:
fill="#a8d4ec", height 32, with a square-bottom patch rect to flatten the lower edge
- Operator name: font-size 12 or 13,
font-weight="bold", fill="#1a1a2e", baseline aligned to the bottom of the header band
- Metric lines: font-size 11,
fill="#222", 18px line spacing, first line starts 14px below the header band bottom
- Highlighted metric lines:
font-weight="bold", fill="#c0392b" for the entire line — do not attempt inline partial coloring (no <tspan>, no nested <text>)
- AQEShuffleRead specifically: use
stroke-width="2.5" to visually distinguish it as the key node
- Stage boxes surrounding the plan: use neutral gray (
fill="#f4f4f4", stroke="#aaa", header fill="#888") — stages are context, not the focus
- CRITICAL — Plan tree direction: upstream (leaf/data source) at TOP, downstream (root/output) at BOTTOM. Spark UI's SQL tab renders the plan tree with the data source (e.g., TableScan, Range) at the top and the final output operator (e.g., HashAggregate (Final)) at the bottom. Arrows point downward showing data flow from source to result. This is the opposite of a call-graph layout where "consumers sit above producers." Always check: the operator closest to the data should be visually highest, and the operator closest to the user's result (or the top of the explain plan text) should be visually lowest.
Sizing and layout
- Stage List Tables use a 680px viewBox and render at full column width — no explicit
max-width constraint needed. The density of data columns justifies the full width.
- Plan Tree Diagrams (SQL plan node style) should be visually compact relative to the text column. Use the following guidelines:
- viewBox width: size to fit the longest text line, not the article container. Add
style="max-width:320px;margin:0 auto;" on the SVG element to prevent it stretching. 320px is correct for compact trees (2–3 nodes like Partial → Exchange → Final). For larger plans with more nodes and wider boxes, use up to 400px.
- viewBox height: set exactly to the bottom edge of the last element —
y + height of the final box. Never leave blank space below.
- Box height formula:
header_height(36) + N_lines × 18 + 14 bottom padding. Compute this per box; do not use a uniform height across boxes with different line counts.
- Arrow center x: always
viewBox_width / 2. Arrow length: 36–40px. Use <polygon> for arrowheads, not <marker>.
- Content x offset: 16px from the left edge of the box (box left edge + 12px margin = 16 if box starts at x=4).
What to highlight vs. leave plain
- Highlight only the metrics that are the point of the diagram. In an Exchange node, highlight the fetch wait time. In AQEShuffleRead, highlight the skew partition counts. Everything else stays
#222.
- Never add explanatory italic annotation text inside boxes. The metrics speak for themselves. Move any needed explanation into the
<figcaption> or the surrounding prose.
- Do not put task counts or stage duration in the header. Place them as regular metric lines in the body, consistent with all other metrics.
- Stage/context boxes are victims, not causes. Color them neutral gray, not red. Reserve red for the plan nodes that reveal the actual problem.
Text safety rules (critical)
- Every metric is a single
<text> element at a unique y. No <tspan>, no nested <text>.
- Estimate text width at font-size 11: roughly 6px per character. Verify the longest line fits within
box_x + box_width - 16px.
- Line spacing is 18px. First content line baseline =
header_band_bottom_y + 14 + 14 (14px cap height + 14px top padding).
- Leave 10–12px between the last line's baseline and the box bottom edge (the 14px bottom padding accounts for descenders).
Academic Style Design Principles
When the selected style is academic, apply these rules instead of the coral defaults above.
Typography hierarchy
- H1: 22px, bold, tight line-height — one per article
- H2: 18px, bold, plain black text — section headers
- H3: 18px, bold — subsection headers
- Body: 18px base (16px on mobile), 1.65 line-height — optimized for reading
- Code:
Inconsolata monospace for blocks, serif for inline (font-family: inherit)
- Lede: normal size, standard margin — understated opening
Color palette (restrained, print-like)
background: #ffffff;
color: #222222;
h1/h2/h3: #000000;
links: #666666;
code-bg: none;
borders: #dddddd;
No accent colors, no tinted callout backgrounds. Callouts use a simple left border (3px solid #999) with no background tint.
Spacing & rhythm
- Container: max-width 720px, centered, 90% width on narrow screens
- Vertical spacing: 30px top padding, generous bottom margin (80px)
- Section dividers: hidden (
display: none) — rely on H2 whitespace alone
- Pre blocks: 15px font, 1.5 line-height, indented 20px from left margin
Mobile responsiveness
Academic articles include the same mobile media query at @media (max-width: 600px):
- Scaled-down body text (16px)
- Reduced container padding (12px)
- Smaller pre blocks (14px font, 12px left margin)
- Tighter list indentation (20px vs 24px)
Structure Template
Every article follows this structure regardless of style:
- Header
- H1 title
- Lede paragraph (
.lede class)
- No metadata line. Do not add category tags, dates, or author names below the lede. The article stands on its content, not on taxonomy badges.
- No concrete source code line numbers (e.g., "lines 221–235"). Readers do not care about line numbers in upstream source files. Reference the rule or file by name only.
- No detailed code snippets from the implementation. Articles are conceptual, not source-code documentation. Explain what the rule does and why it is correct, not how it is coded. Avoid pasting Scala/Java method bodies, API-level identifiers like
getClass or toAttribute.canonicalized, and internal class names beyond what is needed to name the rule. Diagrams and prose carry the argument; code snippets belong in commit messages and Jira tickets.
- Do not cite the test suite as evidence of correctness. "The test suite passes" is not an argument a reader can evaluate. Explain why the optimization is semantically correct from first principles (e.g., the shuffle is absent, so cross-partition merging cannot happen, so the final agg is a no-op). If a particular edge case needs proof, describe the scenario and the reasoning — not the test that covers it.
-
Sections (H2 + divider)
- Each section starts with H2
- Followed by
<hr class="section-divider"> (hidden in academic style via display: none, present in coral style)
- Subsections use H3
-
Content blocks
- Paragraphs with appropriate vertical margins
- Code blocks:
<pre><code> with syntax-appropriate content
- Tables: wrapped in
.table-wrap for mobile scroll
- Callouts: use
<p> with inline style attributes (not <div> with classes). WeChat's editor strips or downgrades <div> elements, removing their inline styles. Use <p> with style="border-left:3px solid #COLOR;background:#BG;padding:12px 18px;margin:22px 0;border-radius:0 6px 6px 0;" instead.
- Figures: SVG diagrams with captions
-
Footer — Do not add a footer. The article should end naturally after the final section. No author name, date, takeaway, or "Related reading" links.
Pre-Output Checklist
Before generating an article:
Style:
Structure:
Typography:
Mobile:
SVG diagrams (if present):
Portability:
Output Format
Always produce a single self-contained .html file:
- Embedded CSS in
<style> block (no external stylesheets)
- Inline SVG for diagrams (no external images)
- No JavaScript required
- Renders correctly in any modern browser
- Copy-paste safe for rich-text editors (Notion, WordPress, etc.)
The generated CSS must match the selected style exactly — reproduce values from the appropriate template (template.html for coral, template-academic.html for academic) rather than improvising.
Cover Images
When the user asks to generate a cover image ("generate cover image", "cover image for this article", etc.), produce a standalone .svg file alongside the article.
Format
- Standalone
.svg file, aspect ratio 2.35:1 (e.g., 1410×600)
- Inline SVG (no external resources, no width/height attributes, use
viewBox)
Design Principles
- Light theme: warm cream/beige backgrounds (
#faf8f5 to #f0ebe3), not dark
- Minimal text: only the article title. No subtitles, no SQL syntax, no body text
- Cartoon + professional: soft rounded shapes, gentle pastels, subtle shadows (
feDropShadow), soft background blobs (feGaussianBlur)
- Balanced layout: if showing before/after, use equal-sized containers on left and right with a connecting element (arrow) in the center
- Informative: convey the core idea visually — e.g., many small elements on one side, one large element on the other, with a transformation arrow
Layout Guidelines
- Place the title at the top (or bottom), never in the middle where it can overlap content
- Use equal-sized panels for before/after comparisons
- Keep text elements inside their containers with padding — do not let labels overflow or overlap borders
- Use decorative elements sparingly: small dots, sparkles, or soft blobs
Color Palette for Covers
- Background: warm cream gradient
- Problem/side: coral tones (
#fca5a5, #f97066)
- Solution/side: green tones (
#6ee7b7, #34d399)
- Accents: amber (
#fbbf24) for highlights
- Text: dark slate (
#1f2937)
Example Usage
Academic style (default):
User: "Write a blog post explaining how Spark's AQE handles skew joins"
→ Skill loads automatically
→ Generates complete HTML file with serif typography, plain bold headers, 720px wide
Coral style:
User: "Write a coral-style blog post about remote shuffle"
→ Detects "coral" keyword
→ Generates complete HTML file with coral H2 badges, sans-serif, 840px wide
Style not specified:
User: "Write a blog post about remote shuffle"
→ No keyword detected
→ Calls AskUserQuestion to let user choose between Academic (default) and Coral
See assets/template.html (coral) and assets/template-academic.html (academic) for the full scaffolds.