Blogger Persona Portfolio (Single-File HTML for Interviews)
The deliverable is a single index.html: all images base64-embedded, double-click to open, and directly shareable via WeChat or email to interviewers.
The structure is fixed across seven sections, connected by a "life timeline"; copy only highlights strengths, and every number must match the account's profile page.
When to Use
- User wants to turn their own blogger account into application materials (New Media / Content Operations / Brand PR roles)
- User wants to create a similar page for another blogger (change persona, change data, without redesigning)
- User has an old portfolio and needs to change colors, structure, or add a report card
What the Deliverable Looks Like
portfolio/
├── index.html ← The only deliverable
├── data.json ← Data source (notes, quarters, brands, identity)
└── assets/ ← Cover images + avatar (embedded during build)
Seven sections (thematic names are swappable; see references/theming.md):
| Section | Content | Key Requirements |
|---|---|---|
| 12:00 Opening | Title + intro + 5-grid data bar | One sentence that restates "what I achieved" |
| 12:15 Works | TOP1 single breakdown + TOP2–5 always visible + TOP6–9 collapsible | Cover must be original photo featuring the person |
| 12:40 Data | Quarterly like trend + share/save ratio bars | Smooth curve with gradient area and stroke animation |
| 13:00 Experience | Narrative + 2×2 report card + fan persona + summary | Numbers split into three tiers: scale/breakout/monetization |
| 13:20 Method | 4 principles, each backed by a numbered piece of evidence | Don't write a principle without data support |
| 13:40 Strengths | 4 ability cards (big number + tags + evidence) | These are strengths, not retrospective; absolutely no problems or plans |
| 14:00 About | Closing sentence + facts table (location/school/account/email) | Makes it easy for the interviewer to copy contact info |
Prerequisites (Step 0: Before Data Collection)
Scraping requires the Xiaohongshu CLI. The CLI is already bundled in this skill (vendor/redbook/, upstream MIT),
so you can just copy the entire skill directory to someone else—they don't need to npm i -g.
bash scripts/doctor.sh # Health check: node / CLI source / cookie / login status
| Check Item | Requirement | If Not Met |
|---|---|---|
| node | ≥ 22 | Install node first; the bundled copy also relies on it |
| CLI | Either global redbook or vendor/redbook/dist/cli.js | Missing vendor/, or run npm i -g @lucasygu/redbook |
| Login status | ~/.redbook/cookies.json valid | bash scripts/redbook.sh auth save, if that fails see CDP method in data-collection doc |
All data-scraping commands go through a launcher bash scripts/redbook.sh <subcommand>: it prefers the global version (upgradeable via npm),
and falls back to the bundled copy, automatically setting REDBOOK_COOKIE_FILE. Writing bare redbook may not work on the user's machine.
Sharing with someone else: just package the entire
blogger-portfolio/directory (includingvendor/, ~1MB). The other person only needs to do two things: install node ≥22, and log in to their Xiaohongshu account once. Do not deletevendor/redbook/to save space—deleting it degrades the skill to "must install npm package first." To upgrade the CLI:npm i -g @lucasygu/redbook@latestthen sync the newdist/andnode_modules/intovendor/redbook/.
Workflow
1. Data Collection
Use the bundled Xiaohongshu CLI to scrape public data (note list, likes/saves/shares, TOP9 covers, quarterly distribution):
RB="bash scripts/redbook.sh"
$RB whoami # First confirm login status
$RB search "<account nickname>" --json # Numeric Xiaohong ID → get userId + xsec_token
$RB user-posts <userId> --xsec-token '<t>' --xsec-source pc_search --all --delay 3000 --json > posts.json
Metrics like page views, fan persona, number of brands, and revenue must be asked from the user.
For full commands, dedup/aggregation scripts, cookie fix, and comment scraping with anti-bot measures, see
references/data-collection.md. Scrape serially with 3s delay; for comments, if you hit a CAPTCHA, stop immediately.
2. Define Persona & Theme
First ask three things: Account positioning (lifestyle/home/parenting/pets/food…), Target job role, and Whether the person appears in photos.
Then follow references/theming.md to select a timeline metaphor, color palette, and section naming.
Default is light paper texture (cream #fbf6ee + apricot orange #d9744f); lifestyle bloggers must not use dark themes.
3. Write data.json
Copy demo/data.json and modify (the demo/ folder is a buildable example with fictional personas and placeholder covers):
{
"site": {"title","meta","name","tagline","handle","profile_url","collected_at","start","avatar"},
"hero": {"clock","h1","lead","roles"},
"ledger":[{"value","label","hl"}], // 5-grid, first cell hl:true
"facts": [{"k","v"}], // About page right-side facts table (location/school/account/email)
"notes": [{"rank","title","date","like","collect","share","comment","url","brand","img"}],
"quarters": [["24Q3", 1, 260]], // [quarter, post count, total likes], 6–12 entries allowed
"brands":[{"name","cat"}]
}
9 notes entries are enough (TOP1 + TOP2–5 + TOP6–9); img uses relative paths, automatically embedded during build.
Keep original platform formatting (e.g., "7.6万"); the page's toN/fmt will normalize.
h1 and lead can contain HTML (<br>, <span class="mark">, <em>).
4. Build
python3 scripts/build.py --data portfolio/data.json --out portfolio/index.html
The script embeds images, fills placeholders, and exits with an error if any placeholder remains unfilled, finally printing how many example copy points still need editing.
5. Rewrite Example Copy (Cannot Skip)
The template includes a complete "car-bed nap" example set. After building, replace each marked section individually:
<!--EDIT:works--> Works section title/lead + TOP1 three-point breakdown
<!--EDIT:featured--> TOP1 highlight card (hook + why it went viral)
<!--EDIT:datahead--> Data section title + three ratio explanations
<!--EDIT:experience--> Experience: narrative + report card + fan persona + summary
<!--EDIT:method--> Four methods
<!--EDIT:strengths--> Four strength cards
<!--EDIT:about--> About + sidebar facts table
For writing rules, section formulas, forbidden list, and which card answers which interview question, see references/copy-playbook.md.
Read it before writing—otherwise it's easy to accidentally write a retrospective.
Suggested order: build first, then edit copy in the HTML; if you later need to modify data.json, remember that rebuilding will overwrite your manual edits.
6. Health Check
npm i playwright-core # Install once in any temp directory
node scripts/verify.js portfolio/index.html
Check at three viewports (1440 / 768 / 390): console errors, whether visible images load, horizontal overflow, whether scroll-triggered reveals complete, curve renders, ratio bar widths are not 0, body text contrast ≥ 4.5. Exit code non-zero if critical issues are found.
Do not send screenshots to the user—only report numerical conclusions; take screenshots only if the user explicitly asks.
7. Delivery
Use present_files to open portfolio/index.html, and state three things in the message:
- What changed in this version (colors / structure / data口径)
- Which numbers don't match the platform display and what you suggest writing instead (do not make up numbers)
- What's still missing: work experience [to be filled in], contact email, whether to publish as an online link
If the user is viewing on a phone, serve via local network preview (~/.workbuddy/live-serve/live_serve.py), don't repeatedly transfer files.
Directory Structure
SKILL.md This file
scripts/build.py data.json + template → single-file HTML
scripts/verify.js Pre-delivery health check (playwright-core + local Chrome)
scripts/doctor.sh Pre-data-collection health check (node / CLI / cookie / login status)
scripts/preview.sh Build + serve + mobile URL + auto-rebuild on changes (single command)
scripts/redbook.sh CLI launcher (prefers global version → falls back to bundled copy, auto-selects)
assets/template.html Page template (full CSS/JS, with placeholders like {{NAME}})
demo/ Buildable example (fictional persona + placeholder covers; run once to verify environment)
references/data-collection.md Scraping, aggregation, cookie repair, anti-bot
references/copy-playbook.md Copy formulas, three-tier numbers, forbidden items, interview question mapping
references/theming.md Reskinning: timeline metaphor, color palette, decorations, accessibility minimums
vendor/redbook/ Bundled Xiaohongshu CLI (MIT, includes dist/ and node_modules/)
vendor/NOTICE.md Source, version, license, and upgrade notes for bundled dependencies
Template is 37KB; final output with embedded images is ~1MB—acceptable size; do not compress images to reduce size. Bundled CLI is ~760KB; do not delete it—it's the only guarantee that "someone can run it after just installing node."
Common Pitfalls
- Contradictory numbers: User says "80k likes", page says 76k—the interviewer will notice instantly. Always use the profile page's displayed values.
- Bare
redbookgives command not found: The user's machine doesn't have the global package. Always usebash scripts/redbook.sh, which falls back tovendor/redbook/; first runbash scripts/doctor.shto see which step is missing. - Writing a retrospective: If you see "problems", "next steps", or "learned", you've gone off track. Delete the entire block and replace it with ability cards.
- Forgetting to sync timestamps: The navigation
<small>12:15</small>must match the section<b>12:15</b>. - Ratio bars not showing:
.bar .tr / .flare spans; they must havedisplay:blockto show width. - Collapsed images report "not loaded": Lazy-loaded images inside
display:noneare expected;verify.jsalready excludes them. - Mobile line breaks: The three fan-persona mini-cards use
white-space:nowrap; on narrow screens, reduce font size and padding. - Large accounts have capped likes: For accounts with 100k+ followers, likes show as "10万+", and
collected_countmay also be capped. Any "saves ÷ likes" ratio is an upper bound and cannot be used as a conclusion—instead, change the ratio bars to absolute values (saves and comments each get their own set). The conclusion still holds, but every number is defensible. - Don't rank large accounts by likes: After capping, the ranking is fake. Instead, pick one representative work per content type, and explain in the subtitle why there's no ranking.
- Mixed cover aspect ratios: The same account may have 9:16, 3:4, and 4:3 covers (long videos, square images, landscape). Crop uniformly to 3:4 +
object-position:50% 42%; vertical versions won't cut off bottom titles. - Hero data bars only occupy half a row: Placing
.ledgerin the hero's second.wrapinherits a two-column grid. Add.hero .wrap+.wrap{display:block}. - Large accounts scrape slowly: For 1000+ posts,
--delay 2000takes ~40 pages and ~2 minutes; but fetching details for TOP9 requires reading each post individually with 5s intervals—do not parallelize.