.claude/skills/ts-blog-article-design/SKILL.md
Design and implement high-quality blog post and article page layouts with professional typography, spacing, and visual hierarchy. Use when building blog pages, article templates, technical documentation readers, use-case pages, or long-form content layouts. Covers dark and light themes.
npx skillsauth add eliferjunior/Claude blog-article-designInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Professional design system for blog posts, articles, and long-form content pages. Based on patterns from Stripe, Vercel, Tailwind, and Linear documentation. Provides specific typography scales, spacing rules, code block styling, and visual hierarchy guidelines optimized for readability on both dark and light themes.
When designing or improving a blog/article page, follow these steps in order.
The single most important decision is content width. Optimal reading length is 60-70 characters per line.
Container width: max-w-2xl (672px) for prose-heavy articles
max-w-3xl (768px) if content includes wide code blocks or tables
Centering: mx-auto
Horizontal pad: px-6 (24px on each side)
Top padding: pt-24 (96px) to clear fixed headers
Bottom padding: pb-16 (64px)
Never use max-w-4xl or wider for article text — lines become too long to read comfortably.
Use a constrained type scale with clear hierarchy. Every level must be visually distinct.
Dark theme (zinc palette):
H1: text-3xl md:text-4xl font-bold text-zinc-50 — Page title, one per page
H2: text-2xl font-semibold tracking-tight text-zinc-50 — Major sections, mt-12 mb-4
H3: text-xl font-semibold tracking-tight text-zinc-50 — Subsections, mt-8 mb-3
H4: text-lg font-semibold text-zinc-100 — Minor headings, mt-6 mb-2
Body: text-base leading-7 text-zinc-300 mb-6 — Paragraphs, 16px/28px
Strong: text-zinc-50 font-semibold — Emphasis within body
Muted: text-zinc-400 — Captions, metadata
Link: text-accent underline decoration-accent/40 — Visible, accessible links
Light theme (gray palette):
H1: text-3xl md:text-4xl font-bold text-gray-900
H2: text-2xl font-semibold tracking-tight text-gray-900
H3: text-xl font-semibold tracking-tight text-gray-900
Body: text-base leading-7 text-gray-600 mb-6
Strong: text-gray-900 font-semibold
Muted: text-gray-500
Key rules:
leading-7 (1.75) for comfortable readingmb-6 creates clear separation without feeling sparsetracking-tight for a polished, dense feelmt-12 — generous top margin signals a new major sectionUnordered: list-disc list-outside pl-6 space-y-2 text-zinc-300 my-6
Ordered: list-decimal list-outside pl-6 space-y-2 text-zinc-300 my-6
List item: text-base leading-7
Inline code: bg-white/10 px-1.5 py-0.5 rounded-md text-[0.9em] font-mono text-zinc-200
Blockquote: border-l-4 border-zinc-700 pl-4 my-6 text-zinc-400 italic
Horizontal rule: border-white/10 my-12
For ordered lists interrupted by other elements (code blocks), preserve the start attribute to maintain correct numbering.
Two distinct code block types:
Language-tagged blocks (syntax-highlighted code):
Container: my-6 rounded-xl border border-white/10 bg-zinc-900 overflow-hidden
Header: flex items-center gap-2 px-4 py-2.5 border-b border-white/5 bg-zinc-900/80
Lang label: text-xs font-mono text-zinc-500
Code area: px-5 py-4 overflow-x-auto
Pre: text-sm leading-relaxed whitespace-pre-wrap break-words
Text/output blocks (untagged or text language):
Container: my-6 rounded-xl border border-white/10 bg-zinc-900 overflow-x-auto
Pre: px-5 py-4 text-sm leading-relaxed whitespace-pre-wrap break-words font-mono
For output blocks, apply line-by-line visual hierarchy:
text-zinc-50 font-semibold (title)text-zinc-100 font-medium (section header): (under 60 chars) → section header style1. ...) → text-zinc-200---, ===) → text-zinc-700text-emerald-400 highlighttext-zinc-400 (body)h-3 spacerWrapper: overflow-x-auto my-6 rounded-xl border border-white/10
Table: w-full text-sm border-collapse
Thead: bg-zinc-900/50
Th: text-left py-3 px-4 text-zinc-200 font-semibold text-xs uppercase tracking-wider
Tr: border-b border-white/5
Td: py-3 px-4 text-zinc-300
A well-structured article page has these sections in order:
1. Breadcrumb — text-sm text-muted, links with hover:text-white
2. Title — H1, single line preferred, bold
3. Metadata bar — category badge, tags, author, date (flex-wrap gap-3)
4. Related resources — linked cards (if applicable)
5. Article body — markdown-rendered content
6. Footer — related articles, share buttons (optional)
Category badge style: text-xs bg-accent/20 text-accent px-2 py-1 rounded capitalize
Tags: text-xs text-muted with # prefix
Mobile (<640px): px-6, text-3xl title, full-width code blocks
Tablet (640px+): Same as mobile but wider line length
Desktop (768px+): text-4xl title, centered container
Code blocks should use overflow-x-auto on mobile and whitespace-pre-wrap break-words to avoid horizontal scroll when possible.
User request: "Create custom markdown components for my blog's article pages with a dark theme"
Implementation:
import React from 'react'
export const markdownComponents = {
h1: () => null, // Title rendered separately above the article
h2: ({ children }: any) => (
<h2 className="text-2xl font-semibold tracking-tight text-zinc-50 mt-12 mb-4">{children}</h2>
),
h3: ({ children }: any) => (
<h3 className="text-xl font-semibold tracking-tight text-zinc-50 mt-8 mb-3">{children}</h3>
),
p: ({ children }: any) => (
<p className="text-base leading-7 text-zinc-300 mb-6">{children}</p>
),
strong: ({ children }: any) => (
<strong className="text-zinc-50 font-semibold">{children}</strong>
),
a: ({ href, children }: any) => (
<a href={href} className="text-emerald-400 underline decoration-emerald-400/40 underline-offset-2 hover:decoration-emerald-400 transition-colors" target="_blank" rel="noopener noreferrer">{children}</a>
),
ul: ({ children }: any) => (
<ul className="list-disc list-outside pl-6 space-y-2 text-zinc-300 my-6">{children}</ul>
),
ol: ({ children, start }: any) => (
<ol start={start} className="list-decimal list-outside pl-6 space-y-2 text-zinc-300 my-6">{children}</ol>
),
li: ({ children }: any) => (
<li className="text-base leading-7 [&>p]:mb-0">{children}</li>
),
code: ({ className, children }: any) => {
if (className?.includes('language-')) return <code className={className}>{children}</code>
return <code className="bg-white/10 px-1.5 py-0.5 rounded-md text-[0.9em] font-mono text-zinc-200">{children}</code>
},
pre: ({ children }: any) => (
<div className="my-6 rounded-xl border border-white/10 bg-zinc-900 overflow-x-auto">
<pre className="px-5 py-4 text-sm leading-relaxed whitespace-pre-wrap break-words">{children}</pre>
</div>
),
table: ({ children }: any) => (
<div className="overflow-x-auto my-6 rounded-xl border border-white/10">
<table className="w-full text-sm border-collapse">{children}</table>
</div>
),
blockquote: ({ children }: any) => (
<blockquote className="border-l-4 border-zinc-700 pl-4 my-6 text-zinc-400 italic [&>p]:mb-0">{children}</blockquote>
),
}
User request: "Build a use-case article page with a breadcrumb, title, category badge, and markdown body"
Implementation:
export default function ArticlePage({ article }) {
return (
<main className="pt-24 pb-16">
<div className="max-w-2xl mx-auto px-6">
{/* Breadcrumb */}
<div className="flex items-center gap-2 text-sm text-zinc-500 mb-8">
<a href="/articles" className="hover:text-white transition-colors">Articles</a>
<span>/</span>
<span className="text-white">{article.title}</span>
</div>
{/* Title */}
<h1 className="text-3xl md:text-4xl font-bold text-zinc-50 mb-4">
{article.title}
</h1>
{/* Metadata */}
<div className="flex flex-wrap items-center gap-3 mb-8">
<span className="text-xs bg-emerald-500/20 text-emerald-400 px-2 py-1 rounded capitalize">
{article.category}
</span>
{article.tags.map(tag => (
<span key={tag} className="text-xs text-zinc-500">#{tag}</span>
))}
</div>
{/* Article body */}
<article>
<ReactMarkdown components={markdownComponents}>
{article.body}
</ReactMarkdown>
</article>
</div>
</main>
)
}
max-w-2xl achieves this at 16px body text. Never go wider for prose.mb-6 on paragraphs and my-6 on blocks creates a predictable reading pace. Headings break the rhythm intentionally with larger top margins.rounded-xl border border-white/10 bg-zinc-900 pattern creates a clean, contained look.overflow-x-auto to handle narrow viewports.underline-offset-2 with partial-opacity decoration is clean.zinc-300 (#d4d4d8) on #09090b background gives ~11:1 contrast ratio. Headings at zinc-50 (#fafafa) give ~18:1. Both well above WCAG AA.development
Expert guidance for Fireworks AI, the platform for running open-source LLMs (Llama, Mixtral, Qwen, etc.) with enterprise-grade speed and reliability. Helps developers integrate Fireworks' inference API, fine-tune models, and deploy custom model endpoints with function calling and structured output support.
development
Convert any website into clean, structured data with Firecrawl — API-first web scraping service. Use when someone asks to "turn a website into markdown", "scrape website for LLM", "Firecrawl", "extract website content as clean text", "crawl and convert to structured data", or "scrape website for RAG". Covers single-page scraping, full-site crawling, structured extraction, and LLM-ready output.
tools
Expert guidance for Firebase, Google's platform for building and scaling web and mobile applications. Helps developers set up authentication, Firestore/Realtime Database, Cloud Functions, hosting, storage, and analytics using Firebase's SDK and CLI.
development
When the user needs to build file upload functionality for a web application. Use when the user mentions "file upload," "image upload," "upload endpoint," "multipart upload," "presigned URL," "S3 upload," "file validation," "upload to cloud storage," or "accept user files." Handles upload endpoints, file validation (type, size, magic bytes), cloud storage integration, and upload status tracking. For image/video processing after upload, see media-transcoder.