Use when the user provides a URL to a web article, blog post, or X Article and wants LaTeX notes rendered as PDF. Triggers: article/blog URL, '整理这篇文章', '文章笔记'. Handles translation detection (traces back to original).
Use this skill to turn a web article, blog post, or X/Twitter article into a complete, compileable .tex note and a rendered PDF.
This skill complements youtube-render-pdf and bilibili-render-pdf for text-based content sources.
| Source | Fetch Method | Notes |
|---|---|---|
| X/Twitter Articles | api.fxtwitter.com/{user}/status/{id} | Full article JSON, zero auth |
| X/Twitter Threads | Same API, recursive via replying_to_status | Chase reply chain |
| Tech blogs | mcp__duckduckgo-search__fetch_content | Anthropic, OpenAI, etc. |
| Official docs | Same as blogs | OpenAI Codex docs, etc. |
| Medium / Substack | WebFetch or fetch_content |
| May need pagination |
Produce a professional Chinese article note from a URL.
The output must:
\section{...} and \subsection{...}.tex document from \documentclass to \end{document}Before processing any article, check if it is a translation:
【译】, [译], 翻译, Translation原文链接, 原文作者, Original by, Source:@dotey 宝玉, @MinLiBuilds 实践哥MinLi)entityMap in fxtwitter response for LINK entities原文链接 or Original:When the translation links to another X post:
# Extract entity URLs from fxtwitter response
article.content.entityMap → look for type: "LINK" entries
# The URL often points to the original author's X article
When the original is a podcast/video:
yt-dlp "ytsearch:SPEAKER PODCAST_NAME YEAR"youtube-transcript-api or auto-captions# Fetch full article JSON (zero auth, no API key needed)
curl -s "https://api.fxtwitter.com/{user}/status/{id}" | python3 -c "
import sys, json
data = json.load(sys.stdin)
tweet = data['tweet']
article = tweet.get('article', {})
blocks = article.get('content', {}).get('blocks', [])
# Extract text with structure
for block in blocks:
btype = block.get('type', '')
text = block.get('text', '')
if 'header' in btype:
print(f'\n## {text}\n')
elif btype == 'unordered-list-item':
print(f'- {text}')
elif btype == 'ordered-list-item':
print(f'1. {text}')
elif btype == 'blockquote':
print(f'> {text}')
elif btype == 'code-block':
print(f\"\`\`\`\n{text}\n\`\`\`\")
else:
print(text)
"
Key fields in the fxtwitter response:
tweet.article.title — article titletweet.article.content.blocks — structured content blockstweet.article.content.entityMap — links, media, embedded tweetstweet.author.name — author display nametweet.created_at — publish datetweet.views — view count# Use fetch_content for full text (supports pagination)
mcp__duckduckgo-search__fetch_content(url, max_length=20000)
# If content exceeds 20K chars, use start_index for pagination
mcp__duckduckgo-search__fetch_content(url, start_index=20000, max_length=20000)
For articles with embedded images:
entityMap entries with type MEDIA<img> tags from fetched HTMLWrite the notes in Chinese unless the user explicitly requests another language.
Organize the document with \section{...} and \subsection{...}.
Reconstruct the teaching flow when needed; do not blindly mirror original article order.
Start from assets/notes-template.tex.
Adapt the metadata block for articles:
课程笔记 to 文章笔记 on the front page\noteauthors{...} → "基于 [Author Name] 文章内容整理". Never use "XX & Codex", "XX & AI", or similar\notedate{...} → the article's actual publish date (e.g., "2025-03-15"). Never use \today\videochannel → article author / source platform\videopublishdate → publish date\videoduration → estimated reading time (e.g., "阅读时长:约 15 分钟")\videourl → article URL (always fill this in — you have the URL the user provided)\videocoverpath → leave empty (articles typically have no cover image)\repourl{https://github.com/hqhq1025/ai-course-notes} → keep the default; do not change or deleteFor translated articles, add a note below the metadata box:
\vspace{0.3cm}
{\small 本笔记基于英文原文整理。原文作者:XXX,译者参考:YYY。\par}
Use highlight boxes deliberately:
importantbox for core concepts, key arguments, design principlesknowledgebox for background context, related work, terminologywarningbox for common misconceptions, pitfalls, caveats the author raisesWhen a mathematical formula or data comparison appears:
$$...$$tabular / booktabs) for structured comparisonsWhen code examples appear:
lstlisting with a descriptive captionPreserve notable quotes from the original author using \textit{...} or the quote environment.
End every major section with \subsection{本章小结}.
Add \subsection{拓展阅读} when there are worthwhile external links.
End the document with \section{总结与延伸} containing:
Do not emit [cite]-style placeholders anywhere in the LaTeX.
articles/
├── anthropic-harness-design/ # kebab-case topic name
│ ├── content.txt # fetched article text
│ ├── metadata.json # author, date, url, type
│ ├── harness-design-notes.tex # LaTeX source
│ └── harness-design-notes.pdf # compiled PDF
├── dotey-karpathy-translation/ # translation example
│ ├── content.txt # translated text (reference)
│ ├── original_content.txt # original English text
│ ├── original_metadata.json # original source metadata
│ ├── metadata.json
│ ├── dotey-karpathy-translation-notes.tex
│ └── dotey-karpathy-translation-notes.pdf
└── ...
The .tex and .pdf files MUST be named <dirname>-notes.tex and <dirname>-notes.pdf, where <dirname> is the article directory name. For example, if the directory is anthropic-harness-design/, the files must be anthropic-harness-design-notes.tex and anthropic-harness-design-notes.pdf. Never use bare notes.tex or other ad-hoc names.
Deliver all of the following:
content.txtmetadata.jsonoriginal_content.txt and original_metadata.json.tex filexelatex -interaction=nonstopmode)cd <article-dir>
xelatex -interaction=nonstopmode <file>.tex # first pass (generate references)
xelatex -interaction=nonstopmode <file>.tex # second pass (resolve references)
ai-course-notes/CLAUDE.md conventions for LaTeX structure, boxes, and figuresxelatex two passes) to resolve referencesassets/notes-template.tex: default LaTeX template to copy and fill