Skills DirectorySkills Directory
SkillsLearnSecurityCategoriesDocsCommunityBlog
Sign InSubmit Skill
Skills Directory

Security-tested agent skills for Claude, coding agents, and AI workflows.

Directory

  • Browse Skills
  • All Skills A–Z
  • Claude Skills
  • Claude Code Skills
  • Agent Skills
  • Categories
  • Submit a Skill

Learn

  • Learn Hub
  • Install Claude Skills
  • Write SKILL.md
  • Skills vs MCP
  • Directories Compared

Security

  • Security
  • Methodology
  • Secure Claude Skills
  • Security Badges

Company

  • About
  • Community
  • Blog
  • API Docs
  • Advertise

2026 Skills Directory. All rights reserved.

Back to skills

Headline Card

ASecurity

Use this skill when the user asks to add news headline cards, 'Last Week Tonight'-style cards, headline slides, news quote slides, or media quote cards to a Typst presentation. Also use when the user wants to modify existing headline cards (add/remove cards, change quotes, swap logos, fix layout issues). Trigger on: 'add a headline', 'news card', 'LWT card', 'headline slide', 'quote card', 'media quote', 'add a quote from [publication]'.

21 stars
0 votes
0 copies
0 views
Added 9/19/2026
content-marketinggobash

Works with

cli

Security Analysis

A100/100

Scanned 9/19/2026

Install to Claude Code

$npx -y skills add edwinhu/workflows --skill headline-card --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Headline Card?

Add the live security badge to your README — it updates automatically with every re-scan.

Security grade badge for Headline Card
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/edwinhu-headline-card/badge)](https://www.skillsdirectory.com/skills/edwinhu-headline-card)

More formats (shields.io, HTML) on the badges page.

Download Zip
Files
SKILL.md
---
name: headline-card
user-invocable: false
description: "Use this skill when the user asks to add news headline cards, 'Last Week Tonight'-style cards, headline slides, news quote slides, or media quote cards to a Typst presentation. Also use when the user wants to modify existing headline cards (add/remove cards, change quotes, swap logos, fix layout issues). Trigger on: 'add a headline', 'news card', 'LWT card', 'headline slide', 'quote card', 'media quote', 'add a quote from [publication]'."
---

# Headline Cards for Typst Presentations

**What this skill carries** — grep `references/` for any subject the names below miss:
!`d=${CLAUDE_SKILL_DIR}; command -v skill-toc >/dev/null 2>&1 && exec skill-toc "$d"; s=$HOME/.claude/skills/plugin-utils/bin/skill-toc; [ -x "$s" ] && exec "$s" "$d"; echo "(skill-toc unavailable: references and scripts are NOT listed here — install the plugin-utils plugin, or start a new session so its bin/ reaches PATH)"`

**Typst rules in force here** — read the one that governs what you are writing; they are independent:
!`k=slides; command -v typst-rules >/dev/null 2>&1 && exec typst-rules "$k"; r=$HOME/.claude/skills/typst/scripts/load-constraints; [ -x "$r" ] && exec "$r" "$k"; r=$HOME/projects/typst/scripts/load-constraints; [ -x "$r" ] && exec "$r" "$k"; echo "(typst corpus unavailable: NO Typst rule is listed here — install the typst plugin, or start a new session so its bin/ reaches PATH)"`

An editorial recreation of a newspaper clipping: **light** paper stock, the real
masthead logo, a top rule carrying a category kicker and dateline, a serif
headline with a Last-Week-Tonight yellow highlighter swipe over one phrase, and a
short standfirst.

**Read `templates/theme.typ` before writing a card.** The implementation is the
authority; if it disagrees with this file, believe it and fix this file.

## Architecture

```
presentation/
├── templates/theme.typ        ← headline-card() lives here; read it first
├── data/headlines-NN.json     ← card data, NN = the lecture number
├── assets/logos/*.svg         ← DARK / full-colour logos (see below)
└── slides/XX-topic/NN.typ     ← loops over the JSON, one slide per card
```

## Step 1: the JSON entry

```json
{
  "venue": "WSJ",
  "date": "June 24, 2026",
  "kicker": "Tech",
  "headline": "The headline exactly as published",
  "highlight": "phrase to swipe in yellow",
  "quote": "The article's own standfirst/dek.",
  "logo": "../assets/logos/wsj.svg"
}
```

`highlight` must be a **substring of `headline`, matching character for
character** — the function splits on it, so a straight quote where the headline
has a curly one silently produces no swipe. `kicker` and `quote` are optional.

**Quote the article, do not summarise it.** The standfirst should be the
publication's own dek or a vivid line from the piece. "Discusses the impact of
proxy advisors" is not a card; "Anyone who gives them money — shame on you" is.

**Nothing on the card may be composed.** Headline, dek, outlet and date are the
article's own or they do not go on the slide — a card asserts that a publication
printed this. Pull them from the record, and if a field cannot be sourced, omit
it rather than inventing it. Note that Reader's
`reader-get-document-details` returns null for `published_date`/`source_url`
while `reader-list-documents --id <id>` returns them populated — check both
before concluding a date is unavailable.

## Step 2: paper stock is per publication

`headline-card` picks the stock from `venue`. FT is famously salmon and the
broadsheets are white; one generic cream for everything reads as wrong to anyone
who knows the paper.

| venue | stock |
|---|---|
| Financial Times, FT | `#FFF1E5` salmon |
| WSJ, NY Times, Bloomberg, ABC News | `#FFFFFF` |
| X, Twitter | `#FFFFFF` — light-mode surface; the mark is black |
| Bluesky, Mastodon, Threads, LinkedIn | `#FFFFFF` — same embed layout; accents `#01A5FF` / `#563ACC` / black / `#0A66C2` |
| anything else | `#F7F4EC` cream fallback |

### Microblog cards are embeds, not clippings

A post takes the same function and the same stock table, but an **embed layout**,
because the masthead layout is what made it read as a clipping *of* a tweet:

```json
{
  "venue": "X",
  "name": "Matt Levine",
  "handle": "@mattlevine",
  "avatar": "../assets/avatars/mattlevine.jpg",
  "date": "3:42 PM · Aug 22, 2026",
  "headline": "The post text, verbatim."
}
```

| slot | embed | newspaper |
|---|---|---|
| mark | top **right** | left, as the masthead |
| identity | avatar + **name over @handle**, left | venue wordmark |
| date | **below** the text, over a hairline | top right, with the kicker |
| text | sans regular 21pt | serif bold 28pt |
| border | `#cfd9de` (X's own) | `#ded7c7`, radius 0.3em |

`name` and `avatar` are optional — with no `name` the handle carries the slot
alone rather than leaving a bold gap, and with no `avatar` the row simply starts
at the name. Secondary text is `#536471`, X's own. Supply `logo` to use a real X
mark; otherwise a bold sans `X` stands in.

**Bluesky and Mastodon take the same layout.** All three microblog embeds have
one shape — avatar + name over handle at the left, mark top right, timestamp
below the text — so this is a venue LIST (`X`, `Twitter`, `Bluesky`,
`Mastodon`, `Threads`, `LinkedIn`), not a branch per platform. Only the mark and its accent differ, and the
handle format is data rather than code: `@user` (X, Threads),
`@user.bsky.social`, `@user@instance.social`. **Every microblog ships its real mark inline.** `post-mark-svg` in `theme.typ`
carries the official path for X, Bluesky, Mastodon, Threads and LinkedIn, each
filled with the platform's own colour, so no deck has to ship a logo asset. The
non-X paths are the simple-icons set (MIT); X's is the official 300×271 mark.
A caller-supplied `logo` still wins over all of them. The letter fallbacks
(`b.`, `m`, `@`, `in`) now only fire for a venue with no path at all.

`X`/`Twitter` is a venue, not a second function. The card suppresses the
newspaper-only chrome for it — top rule, kicker, serif headline face, highlighter
swipe — and takes `handle:` (`"@elonmusk"`) beside the mark. Everything else, the
stock table included, is shared.

Add a venue to the `stocks` dictionary in `theme.typ` rather than passing a
one-off, so the next card for that outlet inherits it. `stock: rgb("…")`
overrides per card when one genuinely differs.

Legibility does not constrain this choice — ink, dek and dateline land within
~1:1 of each other across every stock — so it is purely identity.

## Step 3: the logo

**Dark or full-colour, on a light card.** Not the `-white.svg` variant; those are
for dark backgrounds and are invisible here. Use `wsj.svg`, `nyt-dark.svg`,
`ft-dark.svg`, `abc-news-dark.svg`.

### IRON LAW: real vector logos only

If you catch yourself writing an SVG with `<text>` elements spelling out the
publication name — stop. That is a placeholder, not a logo, and it ships with the
wrong font, weight and spacing.

```bash
grep '<text' assets/logos/publication.svg && echo "FAKE — download a real logo"
```

Download from Wikimedia Commons, the brand's press page, or a logo repo.
Wikimedia has SVGs for essentially every major publication; "I can't find one"
means search harder.

Sizing needs no per-logo tuning: the function normalises by aspect ratio, so a
narrow mark and a wide wordmark carry similar visual weight.

## Step 4: render

```typst
#{
  let cards = json("../../data/headlines-NN.json")
  for card in cards {
    slide[
      #headline-card(
        venue: card.venue,
        date: card.date,
        headline: card.headline,
        quote: card.at("quote", default: none),
        logo: card.at("logo", default: none),
        phrase: card.at("highlight", default: none),
        kicker: card.at("kicker", default: none),
        stock: card.at("stock", default: auto),
      )
    ]
  }
}
```

**One card per slide, and no `===` heading on it.** Grid layouts truncate quotes
and shrink logos below recognition; a heading eats the vertical space the card
fills. Put any section header on the preceding slide.

## Step 5: look at it

Compile, get the page from `find-slide-page`, render it, and read it. What
matters: the logo renders and is dark enough; the swipe covers the intended
phrase; nothing is clipped; no single orphaned word ends the headline or
standfirst.

Fix widows in the **JSON text**, never in Typst — tighten the wording, or join
the last two words with ` `. Never pad with filler to fix a widow.

## Red flags — STOP

| Symptom | Cause | Fix |
|---|---|---|
| Logo invisible | a `-white.svg` on the light card | use the dark/full-colour variant |
| Logo missing entirely | JSON path taken as relative to `slides/` | paths resolve from **theme.typ**: `../assets/logos/…` |
| No yellow swipe | `highlight` is not an exact substring of `headline` | match curly vs straight quotes character for character |
| Card doesn't read as an object on white stock | border derived from the stock is near-white | the border is a fixed grey; do not re-derive it from `newsprint` |
| An FT card looks like every other card | venue missing from the `stocks` dictionary | add it |
| An X post wears a serif headline, a top rule or a yellow swipe | venue not spelled `X`/`Twitter`, so it took the newspaper branch | fix the venue string — never add a second card function |
| Dek is generic | summarised instead of quoted | use the publication's own standfirst |
| A date is invented | it wasn't in the source | omit the field; never fabricate one |
| `<text>` in the logo SVG | placeholder, not a logo | download the real one |

## Facts

- **The dateline is the smallest text on the card**, so it carries its own darker
  grey rather than the dek's `mute`, which lands ~5.3:1 on newsprint and washes
  out under projector gamma.
- **Black on the yellow swipe measures ~13.7:1** — the highlight helps
  readability rather than hurting it, so spend it on the phrase that carries the
  point, never decoratively.

Attribution

edwinhuedwinhu
View sourceMore from edwinhu →
SSkills DirectorySkills Directory

Ship a skill? Prove it's safe.

Free 120-pattern security scan, letter grade, and an embeddable README badge.

Submit a skill

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments (0)

No comments yet. Be the first to comment!

SSkills DirectorySkills Directory

Ship a skill? Prove it's safe.

Free 120-pattern security scan, letter grade, and an embeddable README badge.

Submit a skill

Related Skills

Postiz

Postiz is a tool to schedule social media and chat posts to 28+ channels X, LinkedIn, LinkedIn Page, Reddit, Instagram, Facebook Page, Threads, YouTube, Google My Business, TikTok, Pinterest, Dribbble, Discord, Slack, Kick, Twitch, Mastodon, Bluesky, Lemmy, Farcaster, Telegram, Nostr, VK, Medium, Dev.to, Hashnode, WordPress, ListMonk

21281 votes

Serp Analysis

SERP analysis techniques for intent classification, feature identification, and competitive intelligence. Use when analyzing search results for content strategy.

2831 votes

On Page Seo Auditor

This skill performs detailed on-page SEO audits to identify issues and optimization opportunities. It analyzes all on-page elements that affect search rankings and provides actionable recommendations.

1821 votes

Brand

Brand voice, visual identity, messaging frameworks, asset management, brand consistency. Activate for branded content, tone of voice, marketing assets, brand compliance, style guides.

1240080 votes

Release Announcement

Write a release announcement — changelog, blog post, in-app note, or social post — that leads with user impact, names the audience, and includes upgrade/migration steps without filler.

798220 votes
View all in content-marketing →