SKILL.md
---
name: hugo-blog
description: Use when adding, editing, or publishing blog posts on the Hugo personal site at badran-elshenawy.netlify.app. Use when creating new series posts, rendering R Markdown to markdown, updating the README, or committing and pushing content. Applies to all work in the my_website repository.
---
# Hugo Blog
## Overview
Hugo personal blog for Badran Elshenawy, deployed on Netlify at badran-elshenawy.netlify.app. Posts are authored in R Markdown (`.rmd`), rendered to `.md` via hugodown, and auto-deployed on push to `main`. The site uses the Coder theme (git submodule — never edit `themes/Coder/` directly).
---
## Dual-file pattern
Every post exists as **two committed files**:
| File | Role |
|---|---|
| `content/posts/{name}.rmd` | Source of truth — edit this |
| `content/posts/{name}.md` | Generated output — never edit directly |
The `.md` is always produced by rendering the `.rmd`. If you edit the `.md` directly, it will be overwritten on the next render.
---
## File naming
Use `{series_name}_part_{NN}.rmd` with underscores and zero-padded numbers:
- `tidyverse_to_scverse_part_01.rmd`
- `scrna_seq_series_part_15.rmd`
- `claude_series_part_08.rmd`
- Standalone posts: `my_first_post.rmd`, `vs_code_quarto_visual_mode.rmd`
New series start at `_part_01`. Always check existing posts in `content/posts/` to confirm the next number in a series.
---
## Front matter (YAML)
Required fields — always use `---` delimiters:
```yaml
---
title: "Series Name – Post N: Subtitle"
author: "Badran Elshenawy"
date: 2026-01-01T09:00:00Z
categories: [...]
tags: [...]
description: "..."
slug: "url-friendly-slug"
draft: false
output: hugodown::md_document
aliases:
- /posts/slug_with_underscores/
summary: "..."
featured: true
---
```
- `rmd_hash` is added automatically by hugodown on render — do not write it manually
- `aliases` uses underscores; `slug` uses hyphens
- Dates use ISO 8601 with time: `2026-04-24T09:00:00Z`
---
## Images
Post images live in `content/posts/images/` as PNG, named `{series}_{what_it_shows}.png`, and are referenced as `/posts/images/{name}.png`.
The alt text renders as a **visible caption** under the image (pandoc emits a `<figcaption>`), so write it as a caption, not a description:
- **Short:** one line, roughly 5 to 10 words
- **Informative:** say what the image shows or contrasts, not how it is drawn
- **No visual inventory:** never list panels, colours, characters, labels or icons
| Wrong | Right |
|---|---|
| `![Infographic contrasting finding disk usage with du and with dust. The left panel, labelled the old way, shows a tired scientist...]` | `![du, one level at a time, versus dust, one tree]` |
| `![Side by side comparison of a directory listing rendered by ls and by eza. The left panel...]` | `![The same directory listed by ls and by eza]` |
If a post is drafted with an `IMAGE BRIEF:` placeholder and the image does not exist yet, leave the image line out of the published post rather than shipping a broken image. Add it with a short caption once the image arrives.
---
## Workflow for adding a post
### 1. Invoke md-format
**REQUIRED.** Use the Skill tool to invoke `md-format` on the source file before doing anything else. This is non-negotiable — do not skip it, even for short posts.
`md-format` checks for:
- Missing blank lines before bullet lists (pandoc collapses them horizontally if absent)
- Em dashes in bullet points that should be bold + colon (`**term:** description`)
Apply every fix `md-format` identifies before proceeding to the next step.
### 2. Create the .rmd
Place it at `content/posts/{series_name}_part_{NN}.rmd` with correct YAML front matter.
### 3. Render to .md
```bash
Rscript -e 'rmarkdown::render("content/posts/filename.rmd", output_format = hugodown::md_document())'
```
Run from the repo root. The `.md` is written to the same directory as the `.rmd`.
### 4. Update README.md
Before every push, update `readme.md` in the repo root:
- Increment the post count for the relevant series in the series table
- If it's a new series, add a row to the table
- Increment the total post count in the "X+ posts" line
**Never push without checking README is in sync.** It's fine for intermediate local commits to be out of sync, but not at push time.
### 5. Commit
Lowercase commit messages in the format `{series} post {N}: {topic}`:
```
tidyverse to scverse post 1: why i'm making the switch to python
pseudotime series post 6: choosing methods and troubleshooting
claude series post 14: capstone retrospective
```
Stage both the `.rmd` and `.md`, plus `readme.md` if updated:
```bash
git add content/posts/filename.rmd content/posts/filename.md readme.md
git commit -m "series name post N: topic"
```
### 6. Push
```bash
git push
```
Netlify auto-deploys on push to `main`. No manual deploy step needed.
---
## Development commands
```bash
hugo server -D # local dev with drafts visible
hugo server # local dev without drafts
hugo # production build → public/
```
---
## README series table
The `readme.md` tracks all series. Format:
```markdown
| Series | Posts | Topics |
|--------|-------|--------|
| **Series Name** | N | Brief topic description |
```
When adding the first post of a new series, add a new row. When adding subsequent posts, increment the count for that row.
---
## Common mistakes
| Mistake | Fix |
|---|---|
| Editing the `.md` directly | Always edit the `.rmd` and re-render |
| Forgetting to render after editing `.rmd` | Run the Rscript render command before committing |
| Pushing without updating README | Check series count and total post count first |
| Wrong date format | Use `2026-04-24T09:00:00Z` — ISO 8601 with time and Z |
| Editing `themes/Coder/` | Never — it's a git submodule; changes will be lost |
| Using hyphens in filenames | Use underscores: `tidyverse_to_scverse_part_01.rmd` |
| Missing blank line before bullet list in .rmd | Apply `md-format` before rendering — pandoc will collapse the list |
| Committing only the `.rmd` without the `.md` | Stage both files together |
| Long descriptive alt text on images | It renders as a visible caption; keep it to one short line |
When Claude will use it
Use when adding, editing, or publishing blog posts on the Hugo personal site at badran-elshenawy.