Initial commit
This commit is contained in:
12
.claude-plugin/plugin.json
Normal file
12
.claude-plugin/plugin.json
Normal file
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"name": "open-source",
|
||||
"description": "Collection of skills for general open-source package development and maintenance",
|
||||
"version": "0.0.0-2025.11.28",
|
||||
"author": {
|
||||
"name": "Garrick Aden-Buie (Posit, PBC)",
|
||||
"email": "garrick@posit.co"
|
||||
},
|
||||
"skills": [
|
||||
"./skills/release-post"
|
||||
]
|
||||
}
|
||||
3
README.md
Normal file
3
README.md
Normal file
@@ -0,0 +1,3 @@
|
||||
# open-source
|
||||
|
||||
Collection of skills for general open-source package development and maintenance
|
||||
60
plugin.lock.json
Normal file
60
plugin.lock.json
Normal file
@@ -0,0 +1,60 @@
|
||||
{
|
||||
"$schema": "internal://schemas/plugin.lock.v1.json",
|
||||
"pluginId": "gh:posit-dev/skills:open-source",
|
||||
"normalized": {
|
||||
"repo": null,
|
||||
"ref": "refs/tags/v20251128.0",
|
||||
"commit": "ce081441bd7f0390c6dd3e116be8f633d88e7219",
|
||||
"treeHash": "c5e09a6309d52e85e8671d6b2b58bbfa5a09897a380df94d09a58209e598fa37",
|
||||
"generatedAt": "2025-11-28T10:27:39.596322Z",
|
||||
"toolVersion": "publish_plugins.py@0.2.0"
|
||||
},
|
||||
"origin": {
|
||||
"remote": "git@github.com:zhongweili/42plugin-data.git",
|
||||
"branch": "master",
|
||||
"commit": "aa1497ed0949fd50e99e70d6324a29c5b34f9390",
|
||||
"repoRoot": "/Users/zhongweili/projects/openmind/42plugin-data"
|
||||
},
|
||||
"manifest": {
|
||||
"name": "open-source",
|
||||
"description": "Collection of skills for general open-source package development and maintenance"
|
||||
},
|
||||
"content": {
|
||||
"files": [
|
||||
{
|
||||
"path": "README.md",
|
||||
"sha256": "de17cbd0c2076d3e3ac4f98e41c6e700e6726baec90503fd3c375026021a3787"
|
||||
},
|
||||
{
|
||||
"path": ".claude-plugin/plugin.json",
|
||||
"sha256": "da888cd4dd2b7c4d10e686f0facfb9ce8b0d6b9aa25568d72cc376155580a333"
|
||||
},
|
||||
{
|
||||
"path": "skills/release-post/SKILL.md",
|
||||
"sha256": "77b4f5c981f5a41642c81fc1d84cc63a4e6397c6c8b24ffe0e681627ef86cd53"
|
||||
},
|
||||
{
|
||||
"path": "skills/release-post/references/content-guidelines.md",
|
||||
"sha256": "b4f2960a87352918abd232d86a5a7754f903842a9d8f1e578f5f6b9657a88bae"
|
||||
},
|
||||
{
|
||||
"path": "skills/release-post/references/shiny-formatting.md",
|
||||
"sha256": "30dd05e615eb46fa7db21d20bb02739abe0a7324a524105cf62c21627ca1e014"
|
||||
},
|
||||
{
|
||||
"path": "skills/release-post/references/tidyverse-formatting.md",
|
||||
"sha256": "6f9d8aae3c24f9a81827b89ca3dd05f5817e2e783abdd8d02b1bbdf51f2fec10"
|
||||
},
|
||||
{
|
||||
"path": "skills/release-post/scripts/get_contributors.R",
|
||||
"sha256": "93a03708015bf7ea7af2478004817892b5f11e65c92f934d0f73cd1481109f1b"
|
||||
}
|
||||
],
|
||||
"dirSha256": "c5e09a6309d52e85e8671d6b2b58bbfa5a09897a380df94d09a58209e598fa37"
|
||||
},
|
||||
"security": {
|
||||
"scannedAt": null,
|
||||
"scannerVersion": null,
|
||||
"flags": []
|
||||
}
|
||||
}
|
||||
285
skills/release-post/SKILL.md
Normal file
285
skills/release-post/SKILL.md
Normal file
@@ -0,0 +1,285 @@
|
||||
---
|
||||
name: release-post
|
||||
description: >
|
||||
Create professional package release blog posts following Tidyverse or Shiny blog conventions.
|
||||
Use when the user needs to: (1) Write a release announcement blog post for an R or Python package
|
||||
for tidyverse.org or shiny.posit.co, (2) Transform NEWS/changelog content into blog format,
|
||||
(3) Generate acknowledgments sections with contributor lists, (4) Format posts following specific
|
||||
blog platform requirements. Supports both Tidyverse (hugodown) and Shiny (Quarto) blog formats with
|
||||
automated contributor fetching and comprehensive style guidance.
|
||||
---
|
||||
|
||||
# Package Release Post
|
||||
|
||||
Create professional R/Python package release blog posts following Tidyverse or Shiny blog conventions.
|
||||
|
||||
## Quick Start
|
||||
|
||||
1. **Identify the blog platform**: Tidyverse (tidyverse.org) or Shiny (shiny.posit.co)
|
||||
2. Verify NEWS.md or changelog exists for the package
|
||||
3. Gather package info: name, version, repository (e.g., "tidyverse/dplyr")
|
||||
4. Follow the workflow below
|
||||
5. Use `scripts/get_contributors.R` to generate acknowledgments
|
||||
6. Reference the appropriate formatting guide for final polish
|
||||
|
||||
## Platform Selection
|
||||
|
||||
This skill supports two blog platforms with different formatting requirements:
|
||||
|
||||
- **Tidyverse blog** (tidyverse.org)
|
||||
- Uses hugodown
|
||||
- R packages primarily
|
||||
- More rigid structure and conventions
|
||||
- See `references/tidyverse-formatting.md`
|
||||
|
||||
- **Shiny blog** (shiny.posit.co)
|
||||
- Uses Quarto
|
||||
- R and Python packages
|
||||
- More flexible, feature-focused structure
|
||||
- See `references/shiny-formatting.md`
|
||||
|
||||
**First, determine which platform the post is for**, then follow the general workflow and apply platform-specific formatting.
|
||||
|
||||
## General Workflow
|
||||
|
||||
These steps apply to both platforms. Content guidelines are based on Tidyverse best practices but adapt them as needed for Shiny posts.
|
||||
|
||||
### Step 1: Gather Information
|
||||
|
||||
Collect required information:
|
||||
|
||||
- **Platform**: Tidyverse or Shiny blog?
|
||||
- **Package name and version**: e.g., "dplyr 1.2.0" or "shiny 1.9.0"
|
||||
- **Repository**: GitHub repo in "owner/repo" format
|
||||
- **Package language**: R or Python
|
||||
- **NEWS content**: Read the package's NEWS.md, CHANGELOG, or NEWS
|
||||
- **Package description**: One-sentence core purpose
|
||||
- **Previous release tag**: For contributor fetching (optional)
|
||||
- **Featured image**: For frontmatter (optional but recommended)
|
||||
|
||||
### Step 2: Structure the Post
|
||||
|
||||
Create the post outline following this order:
|
||||
|
||||
1. **Frontmatter**: Platform-specific YAML (see formatting references)
|
||||
|
||||
2. **Title and Opening**:
|
||||
- Title: Package name and version
|
||||
- Opening: Announcement with one-sentence package description
|
||||
- Installation: Code block with installation command
|
||||
- Overview: Brief summary with link to full release notes
|
||||
|
||||
3. **Main Content** (choose appropriate sections):
|
||||
- **Migration guide** (if breaking changes) - Always first when present
|
||||
- **Lifecycle changes** (deprecations, soft-deprecations, defunct)
|
||||
- **Feature sections** (one per major feature, descriptive headings)
|
||||
- **Minor improvements** (bulleted list)
|
||||
|
||||
4. **Acknowledgements** (when appropriate):
|
||||
- Use `scripts/get_contributors.R`
|
||||
- Format: "A big thank you to all the folks who helped make this release happen:"
|
||||
- Comma-separated GitHub links
|
||||
|
||||
### Step 3: Apply Content Guidelines
|
||||
|
||||
Follow the best practices in `references/content-guidelines.md`:
|
||||
|
||||
- **Opening style**: "We're [random adjective expressing excitement] to announce the release of..."
|
||||
- **Section organization**: Migration → Lifecycle → Features → Improvements → Acknowledgements
|
||||
- **Tone**: Conversational, professional, enthusiastic but authentic
|
||||
- **Technical precision**: Use exact function names in backticks
|
||||
- **Focus on benefits**: Explain "why" not just "what"
|
||||
- **Code examples**: Realistic, well-commented, properly formatted
|
||||
|
||||
### Step 4: Transform NEWS Content
|
||||
|
||||
Convert NEWS.md bullets to blog-friendly content:
|
||||
|
||||
- **Research features thoroughly**: Don't just copy NEWS bullets—read function docs, check PRs, understand the context
|
||||
- **Expand context**: Why changes matter, not just what changed
|
||||
- **Add complete code examples**: Show realistic usage with full workflows, not just function signatures
|
||||
- **Explain concepts first**: For unfamiliar features, explain what they are and how they work before showing code
|
||||
- **Group thematically**: Combine related NEWS items into coherent sections
|
||||
- **Use conversational tone**: Transform terse bullets into prose
|
||||
- **Link documentation**: Add relevant links to docs and resources
|
||||
- **Highlight breaking changes**: Make migration paths clear
|
||||
- **Multi-language parity** (Shiny only): For R+Python packages on the Shiny blog, ensure all examples show both languages in tabsets
|
||||
|
||||
### Step 5: Apply Platform-Specific Formatting
|
||||
|
||||
**For Tidyverse posts**, read `references/tidyverse-formatting.md` and apply:
|
||||
- hugodown frontmatter with `slug`, `photo.url`, `photo.author`
|
||||
- Specific slug format: `packagename-x-y-z` (hyphens replace dots)
|
||||
- R code blocks with `r` language identifier
|
||||
- Acknowledgements always included as final section
|
||||
|
||||
**For Shiny posts**, read `references/shiny-formatting.md` and apply:
|
||||
- Quarto frontmatter with YAML anchors for social media
|
||||
- Flexible title formatting
|
||||
- Use tabsets for Python/R or Express/Core variations
|
||||
- Platform-specific code block attributes
|
||||
- Acknowledgements optional, varies by post type
|
||||
- May use lead paragraphs, callouts, embedded media
|
||||
|
||||
### Step 6: Generate Acknowledgements
|
||||
|
||||
Run the contributor script:
|
||||
|
||||
```bash
|
||||
Rscript scripts/get_contributors.R "owner/repo"
|
||||
```
|
||||
|
||||
Or with a specific starting tag for the previous version (or tag used for last release post):
|
||||
|
||||
```bash
|
||||
Rscript scripts/get_contributors.R "owner/repo" "v1.0.0"
|
||||
```
|
||||
|
||||
Copy the markdown output into the Acknowledgements section.
|
||||
|
||||
### Step 7: Review and Polish
|
||||
|
||||
Platform-agnostic checklist:
|
||||
|
||||
- [ ] Frontmatter complete with all required fields
|
||||
- [ ] Opening clearly states package purpose
|
||||
- [ ] Installation code block present (both languages if applicable)
|
||||
- [ ] Sections organized logically
|
||||
- [ ] Code examples use proper syntax highlighting
|
||||
- [ ] Function names in backticks with parentheses: `` `function()` ``
|
||||
- [ ] Package names are not backticked or otherwise styled
|
||||
- [ ] Tone is conversational but not marketing-speak
|
||||
- [ ] No superlatives ("powerful", "rich", "seamless", etc.)
|
||||
- [ ] Features explained with context, not just listed
|
||||
- [ ] Concepts explained before showing code
|
||||
- [ ] All examples show R and Python variants (if applicable)
|
||||
- [ ] Links to full release notes included
|
||||
|
||||
Platform-specific checklist:
|
||||
|
||||
**Tidyverse:**
|
||||
- [ ] Slug format: `package-x-y-z` (hyphens, not dots)
|
||||
- [ ] Photo URL and author included
|
||||
- [ ] Acknowledgements section is final section
|
||||
- [ ] All contributors listed alphabetically
|
||||
|
||||
**Shiny:**
|
||||
- [ ] YAML anchors used for description (`&desc`, `*desc`)
|
||||
- [ ] Social media cards configured (`open-graph`, `twitter-card`)
|
||||
- [ ] Appropriate filters specified if using tabsets/shinylive
|
||||
- [ ] Tabsets used for showing paired variants (Python/R, Express/Core)
|
||||
- [ ] Multi-language tabsets used consistently (for R+Python packages only)
|
||||
|
||||
## Reference Documentation
|
||||
|
||||
Load these as needed for detailed guidance:
|
||||
|
||||
### Content Guidelines
|
||||
**`references/content-guidelines.md`** - General best practices for all release posts:
|
||||
- Post structure and organization
|
||||
- Opening style and tone
|
||||
- Section hierarchy and organization
|
||||
- Code examples and formatting
|
||||
- Before/after patterns
|
||||
- Acknowledgments conventions
|
||||
|
||||
### Platform-Specific Formatting
|
||||
|
||||
**`references/tidyverse-formatting.md`** - Tidyverse blog requirements:
|
||||
- hugodown frontmatter structure
|
||||
- Slug and title conventions
|
||||
- Photo attribution
|
||||
- Code block formatting
|
||||
- Lifecycle section structure
|
||||
- Acknowledgements format
|
||||
|
||||
**`references/shiny-formatting.md`** - Shiny blog requirements:
|
||||
- Quarto frontmatter with YAML anchors
|
||||
- Social media card configuration
|
||||
- Lead paragraphs and callouts
|
||||
- Tabsets for variants
|
||||
- Line highlighting and annotations
|
||||
- Video embedding
|
||||
- Flexible acknowledgements
|
||||
|
||||
## Resources
|
||||
|
||||
- **`scripts/get_contributors.R`**: Fetch formatted contributor list using `usethis::use_tidy_thanks()`
|
||||
- **`references/content-guidelines.md`**: General content best practices (platform-agnostic)
|
||||
- **`references/tidyverse-formatting.md`**: Tidyverse-specific formatting requirements
|
||||
- **`references/shiny-formatting.md`**: Shiny-specific formatting requirements
|
||||
|
||||
## Platform-Specific Quick Reference
|
||||
|
||||
### Tidyverse Post Template
|
||||
|
||||
````markdown
|
||||
---
|
||||
output: hugodown::hugo_document
|
||||
slug: package-x-y-z
|
||||
title: package x.y.z
|
||||
date: YYYY-MM-DD
|
||||
author: Your Name
|
||||
description: >
|
||||
Brief description
|
||||
photo:
|
||||
url: https://unsplash.com/photos/id
|
||||
author: Photographer Name
|
||||
categories: [package]
|
||||
tags: [package]
|
||||
---
|
||||
|
||||
# package x.y.z
|
||||
|
||||
We're pleased to announce the release of package x.y.z...
|
||||
|
||||
```r
|
||||
install.packages("package")
|
||||
```
|
||||
|
||||
...
|
||||
|
||||
## Acknowledgements
|
||||
|
||||
A big thank you to all the folks who helped make this release happen:
|
||||
|
||||
[Contributors from get_contributors.R]
|
||||
````
|
||||
|
||||
### Shiny Post Template
|
||||
|
||||
````markdown
|
||||
---
|
||||
title: Package Name x.y.z
|
||||
description: &desc |
|
||||
Brief description of the release.
|
||||
author: "Your Name"
|
||||
date: "YYYY-MM-DD"
|
||||
|
||||
image: feature.png
|
||||
|
||||
open-graph:
|
||||
image: feature.png
|
||||
description: *desc
|
||||
twitter-card:
|
||||
image: feature.png
|
||||
description: *desc
|
||||
---
|
||||
|
||||
# package x.y.z
|
||||
|
||||
We're excited to announce package x.y.z...
|
||||
|
||||
[Installation for Python or R]
|
||||
|
||||
...
|
||||
````
|
||||
|
||||
## Tips
|
||||
|
||||
- **Breaking changes first**: Put migration guides before features
|
||||
- **Highlight the wins**: Lead with the most exciting features
|
||||
- **Show don't tell**: Use code examples liberally
|
||||
- **Link generously**: Help readers find more information
|
||||
- **Keep it conversational**: Write like you're explaining to a colleague
|
||||
- **Be authentic**: Enthusiasm should feel genuine, not marketing-speak
|
||||
409
skills/release-post/references/content-guidelines.md
Normal file
409
skills/release-post/references/content-guidelines.md
Normal file
@@ -0,0 +1,409 @@
|
||||
# Content Guidelines for Release Posts
|
||||
|
||||
General best practices for release post content, regardless of blog platform. These guidelines are based primarily on Tidyverse blog conventions, which provide a principled approach to announcing package updates.
|
||||
|
||||
## Table of Contents
|
||||
|
||||
1. [Post Structure](#post-structure)
|
||||
2. [Opening Style](#opening-style)
|
||||
3. [Section Organization](#section-organization)
|
||||
4. [Tone and Voice](#tone-and-voice)
|
||||
5. [Code Examples](#code-examples)
|
||||
6. [Acknowledgments](#acknowledgments)
|
||||
|
||||
## Post Structure
|
||||
|
||||
Standard structure for release posts:
|
||||
|
||||
```markdown
|
||||
[Frontmatter - see formatting guides]
|
||||
|
||||
# Package Version
|
||||
|
||||
[Opening paragraph with package description]
|
||||
|
||||
[Installation instructions]
|
||||
|
||||
[Overview paragraph about the release]
|
||||
|
||||
## Major Feature 1
|
||||
[Content...]
|
||||
|
||||
## Major Feature 2
|
||||
[Content...]
|
||||
|
||||
## Minor improvements
|
||||
[Bulleted list...]
|
||||
|
||||
## Acknowledgements
|
||||
[Contributor list]
|
||||
```
|
||||
|
||||
## Opening Style
|
||||
|
||||
### Opening Paragraph Pattern
|
||||
|
||||
Start with an announcement that establishes the package's core purpose:
|
||||
|
||||
> "We're [pleased/chuffed/stoked/thrilled/delighted/excited/...] to announce the release of [package] [version]. [Package] [core purpose description in one sentence]."
|
||||
|
||||
**Examples:**
|
||||
- "We're chuffed to announce the release of testthat 3.3.0. testthat makes it easy to turn your existing informal tests into formal, automated tests"
|
||||
- "We're pleased to announce the release of pkgdown 2.2.0. pkgdown is designed to make it quick and easy to build a beautiful and accessible website"
|
||||
- "We're excited to announce the new Shiny extension for VS Code!"
|
||||
|
||||
**Vocabulary variations:**
|
||||
- Choose an upbeat and random adjective with connotations of excitement.
|
||||
- Be interesting and bold, but above all positive and fun.
|
||||
|
||||
### Installation Instructions
|
||||
|
||||
Follow the opening with installation instructions as a code block:
|
||||
|
||||
**R packages:**
|
||||
```r
|
||||
install.packages("packagename")
|
||||
```
|
||||
|
||||
For multiple packages:
|
||||
```r
|
||||
install.packages(c("shiny", "bslib"))
|
||||
```
|
||||
|
||||
**Python packages:**
|
||||
```bash
|
||||
pip install packagename
|
||||
```
|
||||
|
||||
With extras:
|
||||
```bash
|
||||
pip install "packagename[extra]"
|
||||
```
|
||||
|
||||
### Overview Paragraph
|
||||
|
||||
Brief overview of the release following installation:
|
||||
|
||||
- Link to full release notes when available
|
||||
- Highlight focus areas: "This release focuses on [key themes]"
|
||||
- Set expectations: "This is a [major/minor] release with [X main features]"
|
||||
- Acknowledge breaking changes: "This release includes a number of new features... Some of these changes may require you to update your existing code"
|
||||
|
||||
## Section Organization
|
||||
|
||||
### Standard Section Hierarchy
|
||||
|
||||
Organize content in this order:
|
||||
|
||||
1. **Migration guide** (if breaking changes)
|
||||
- Put this first when there are breaking changes
|
||||
- Use clear before/after examples
|
||||
- Explain the rationale for changes
|
||||
|
||||
2. **Lifecycle changes** (if applicable but not breaking)
|
||||
- Soft deprecations
|
||||
- Deprecations
|
||||
- Defunct (removed) functions
|
||||
- Non-breaking behavioral changes
|
||||
|
||||
3. **Major new features** (primary content)
|
||||
- One section per major feature or theme
|
||||
- Use descriptive headings
|
||||
- Lead with what the feature does and why it matters
|
||||
- Include examples
|
||||
|
||||
4. **Minor improvements** or **Other new features**
|
||||
- Bulleted list of smaller enhancements
|
||||
- Brief explanations
|
||||
- Can group related items
|
||||
|
||||
5. **Acknowledgements** (always final)
|
||||
- Thank contributors
|
||||
- List all contributors with GitHub links
|
||||
|
||||
### Section Heading Style
|
||||
|
||||
- Use sentence case: "Lifecycle changes" not "Lifecycle Changes"
|
||||
- Be descriptive: "Easier `in_parallel()`" not just "New feature"
|
||||
- Include function names in backticks when relevant
|
||||
- Make headings scannable and informative
|
||||
|
||||
### Content Organization Within Sections
|
||||
|
||||
**For migration guides:**
|
||||
```markdown
|
||||
## Migrating to vX.Y.Z
|
||||
|
||||
### Setting the app theme
|
||||
|
||||
Prior to vX.Y.Z, you could...
|
||||
|
||||
[Before example]
|
||||
|
||||
**With packagename vX.Y.Z,** you now need to...
|
||||
|
||||
[After example]
|
||||
|
||||
Read about [the feature](#feature) below to learn why this change was needed.
|
||||
```
|
||||
|
||||
**For lifecycle changes:**
|
||||
```markdown
|
||||
## Lifecycle changes
|
||||
|
||||
* **Fully removed** after 5+ years of deprecation:
|
||||
* `function1()` - use `replacement1()` instead
|
||||
* `function2()` - use `replacement2()` instead
|
||||
|
||||
* **Newly deprecated** (soft-deprecation):
|
||||
* `function3()` is superseded by `function4()`
|
||||
* `function5()` is no longer recommended
|
||||
|
||||
* **Breaking changes**:
|
||||
* Brief description of the change and impact
|
||||
```
|
||||
|
||||
**For feature sections:**
|
||||
- Lead with a clear description of what the feature does
|
||||
- Provide context on why it's useful or what problem it solves
|
||||
- Include code examples showing usage
|
||||
- Explain configuration options if relevant
|
||||
- Link to relevant documentation
|
||||
|
||||
### Deep Dives on Features
|
||||
|
||||
Don't just list features from NEWS—research them and provide comprehensive explanations:
|
||||
|
||||
**Transform NEWS bullets into complete sections:**
|
||||
|
||||
1. **Research the feature**:
|
||||
- Read function documentation
|
||||
- Check related PRs and issues for context
|
||||
- Understand the motivation and use cases
|
||||
|
||||
2. **Add complete code examples**:
|
||||
- Show realistic usage, not just function signatures
|
||||
- Include comments explaining what's happening
|
||||
- Demonstrate the full workflow, not just isolated calls
|
||||
|
||||
3. **Explain the context**:
|
||||
- Why was this feature added?
|
||||
- What problem does it solve?
|
||||
- What are the practical use cases?
|
||||
- How does it fit into typical workflows?
|
||||
|
||||
4. **Show use cases and applications**:
|
||||
- Provide examples of when users would need this
|
||||
- Explain different configuration options
|
||||
- Show how features work together
|
||||
|
||||
**Example transformation:**
|
||||
|
||||
❌ **NEWS bullet approach:**
|
||||
```markdown
|
||||
## Bookmarking
|
||||
- Added `chat_restore()` for bookmarking support (#82)
|
||||
```
|
||||
|
||||
✅ **Deep dive approach:**
|
||||
```markdown
|
||||
### Bookmarking support
|
||||
|
||||
shinychat now supports Shiny's bookmarking feature for saving and restoring chat sessions.
|
||||
The new `chat_restore()` function saves the chat client state and restores the message history:
|
||||
|
||||
[Complete code example showing actual usage]
|
||||
|
||||
By default, `chat_restore()` automatically updates the bookmark when users submit messages
|
||||
and when the LLM completes its response. This means users can refresh the page or share a
|
||||
URL and pick up right where they left off.
|
||||
|
||||
For apps with large chat histories, you can use `enableBookmarking = "server"` to store
|
||||
state server-side without URL size limitations.
|
||||
```
|
||||
|
||||
**Research sources:**
|
||||
- Use `r-btw` tools to read R function documentation
|
||||
- Read GitHub PRs/issues linked in NEWS
|
||||
- Check package vignettes and articles
|
||||
- Look at example apps in the repository
|
||||
|
||||
**For improvements:**
|
||||
```markdown
|
||||
## Minor improvements
|
||||
|
||||
* Brief description of improvement with function name in backticks
|
||||
* Another improvement with relevant technical details
|
||||
* Performance gains quantified when possible (e.g., "2x faster")
|
||||
```
|
||||
|
||||
## Tone and Voice
|
||||
|
||||
### Writing Style
|
||||
|
||||
- **Conversational but professional**: "We're excited to announce" rather than "It is announced"
|
||||
- **Inclusive**: Use "we" and "you" rather than passive voice
|
||||
- **Enthusiastic but authentic**: Avoid over-the-top marketing language
|
||||
- **Technical precision**: Use exact function names, parameter names, and technical terms
|
||||
- **Focus on benefits**: Explain the "why" not just the "what"
|
||||
|
||||
### Avoiding Marketing Speak
|
||||
|
||||
Release posts should be friendly and instructional, not advertising. Watch for and remove:
|
||||
|
||||
**Superlatives and promotional adjectives:**
|
||||
- ❌ "powerful set of features", "rich, interactive displays", "beautiful interface"
|
||||
- ✅ "set of features", "interactive displays", "interface"
|
||||
|
||||
**Exaggerated benefit claims:**
|
||||
- ❌ "handles all the complexity of persisting state"
|
||||
- ✅ "saves the chat client state and restores the message history"
|
||||
|
||||
**Generic enthusiasm:**
|
||||
- ❌ "opens up exciting possibilities for building transparent, user-friendly AI applications"
|
||||
- ✅ Direct description of what the feature does
|
||||
|
||||
**Over-hyped capability statements:**
|
||||
- ❌ "give you fine-grained control over every aspect"
|
||||
- ✅ "lets you control the chat interface"
|
||||
|
||||
**Tone review checklist:**
|
||||
- [ ] Remove words like "powerful", "robust", "seamless", "elegant", "revolutionary"
|
||||
- [ ] Replace "makes it easy to" with direct descriptions of functionality
|
||||
- [ ] Prefer descriptive statements focusing on what the function does
|
||||
- [ ] Avoid overuse of phrases that sound like product marketing ("best-in-class", "production-ready")
|
||||
|
||||
|
||||
### Common Phrases
|
||||
|
||||
- "We're [emotion] to announce..."
|
||||
- "A big thank you to all the folks who helped make this release happen"
|
||||
- "You can see a full list of changes in the release notes"
|
||||
- "This makes it easier to..."
|
||||
- "We've improved..."
|
||||
- "This release focuses on..."
|
||||
- "Prior to vX.Y.Z, you had to..."
|
||||
- "With this release, you can now..."
|
||||
|
||||
### Technical Voice
|
||||
|
||||
- Use backticks for all code elements: `` `function()` ``, `` `argument` ``, `` `"value"` ``
|
||||
- Link to relevant documentation when helpful
|
||||
- Be specific about behavior: "returns `NULL`" not "returns nothing"
|
||||
- Explain technical decisions when they impact users
|
||||
- Acknowledge tradeoffs when present
|
||||
|
||||
## Code Examples
|
||||
|
||||
### Explain Concepts Before Code
|
||||
|
||||
For features that introduce new or unfamiliar concepts, explain the concept first before showing code:
|
||||
|
||||
**Pattern: Concept → How it works → Why it matters → Code**
|
||||
|
||||
1. **What is the feature/concept?** (1-2 sentences)
|
||||
2. **How does it work?** (Especially non-obvious aspects)
|
||||
3. **Why does it matter?** (Practical implications)
|
||||
4. **Show the code** (With examples)
|
||||
|
||||
**Key principles:**
|
||||
- Assume readers may not be familiar with the concept
|
||||
- Explain non-obvious aspects clearly
|
||||
- Connect concepts to practical outcomes
|
||||
- Use plain language before technical language
|
||||
|
||||
### Inline Code
|
||||
|
||||
- Function names: `` `map_chr()` ``
|
||||
- Arguments: `` `na.rm = TRUE` ``
|
||||
- Values: `` `NULL` ``, `` `TRUE` ``, `` `"string"` ``
|
||||
- File paths: `` `app.py` ``
|
||||
|
||||
### Code Block Principles
|
||||
|
||||
- Use realistic but simple examples
|
||||
- Include expected output when relevant
|
||||
- Show error messages for examples of better error handling
|
||||
- Format multi-line function calls with proper indentation
|
||||
- Add comments for clarity when needed: `# This does X`
|
||||
- Keep examples focused on the feature being demonstrated
|
||||
|
||||
### Before/After Examples
|
||||
|
||||
When showing improvements, use clear before/after structure:
|
||||
|
||||
```markdown
|
||||
Previously, you had to write:
|
||||
|
||||
[Code block showing old approach]
|
||||
|
||||
Now you can write:
|
||||
|
||||
[Code block showing new approach]
|
||||
```
|
||||
|
||||
Or for migration guides:
|
||||
|
||||
```markdown
|
||||
**Before:**
|
||||
|
||||
[Old code]
|
||||
|
||||
**After:**
|
||||
|
||||
[New code]
|
||||
```
|
||||
|
||||
## Acknowledgments
|
||||
|
||||
### When to Include
|
||||
|
||||
- **Always include** for package releases with external contributors
|
||||
- Optional for internal tooling announcements
|
||||
- Include at the end as the final section
|
||||
|
||||
### Section Format
|
||||
|
||||
```markdown
|
||||
## Acknowledgements
|
||||
|
||||
A big thank you to all [the folks/everyone] who [helped make this release happen/contributed to this release]:
|
||||
|
||||
[@username1](https://github.com/username1), [@username2](https://github.com/username2), ...
|
||||
```
|
||||
|
||||
### Fetching Contributors
|
||||
|
||||
Use `usethis::use_tidy_thanks()` in R:
|
||||
|
||||
```r
|
||||
# From last release to current
|
||||
usethis::use_tidy_thanks("owner/repo")
|
||||
|
||||
# From specific tag/SHA
|
||||
usethis::use_tidy_thanks("owner/repo", from = "v1.0.0")
|
||||
```
|
||||
|
||||
This generates properly formatted markdown for the contributor list that can be included verbatim.
|
||||
|
||||
## Transforming NEWS to Blog Content
|
||||
|
||||
When converting NEWS.md entries to blog post format:
|
||||
|
||||
1. **Expand context**: Technical bullets become paragraphs explaining why changes matter
|
||||
2. **Add examples**: Include code demonstrating new features or changes
|
||||
3. **Group thematically**: Combine scattered NEWS items into coherent sections
|
||||
4. **Use conversational tone**: Transform terse bullets into readable prose
|
||||
5. **Link proactively**: Add links to relevant documentation and resources
|
||||
6. **Focus on user impact**: Explain how changes affect typical usage
|
||||
7. **Highlight breaking changes**: Make migration paths clear and prominent
|
||||
|
||||
## Release Notes Link
|
||||
|
||||
Always include a link to full release notes:
|
||||
|
||||
```markdown
|
||||
You can see a full list of changes in the [release notes](url).
|
||||
```
|
||||
|
||||
This allows readers to find exhaustive details while keeping the blog post focused and readable.
|
||||
606
skills/release-post/references/shiny-formatting.md
Normal file
606
skills/release-post/references/shiny-formatting.md
Normal file
@@ -0,0 +1,606 @@
|
||||
# Shiny Blog Formatting Conventions
|
||||
|
||||
Shiny-specific formatting requirements for blog posts on shiny.posit.co. These conventions are for the Quarto-based Shiny blog.
|
||||
|
||||
## Frontmatter Format
|
||||
|
||||
Shiny blog posts use Quarto YAML frontmatter with this structure:
|
||||
|
||||
```yaml
|
||||
---
|
||||
title: Package Name Version
|
||||
description: &desc |
|
||||
Brief description of the package and release.
|
||||
author: "Author Name"
|
||||
date: "YYYY-MM-DD"
|
||||
|
||||
image: &img feature.png
|
||||
|
||||
open-graph:
|
||||
image: *img
|
||||
description: *desc
|
||||
twitter-card:
|
||||
image: *img
|
||||
description: *desc
|
||||
---
|
||||
```
|
||||
|
||||
### Required Fields
|
||||
|
||||
- **`title`**: Display title (no specific format required, flexible)
|
||||
- Can be: `"packagename version"`, `"Package Name x.y.z"`, or descriptive
|
||||
- Examples:
|
||||
- `"shinyswatch 0.7.0"`
|
||||
- `"Reintroducing the Shiny Extension for VS Code"`
|
||||
- `"Branded theming for Shiny for Python apps"`
|
||||
- **`description`**: Brief summary with YAML anchor for reuse
|
||||
- Use `&desc` anchor and `|` for multi-line
|
||||
- Reuse in social media cards with `*desc`
|
||||
- **`author`**: Author name in quotes (can be single string or array)
|
||||
- Single: `"Garrick Aden-Buie"`
|
||||
- Multiple: `["Author One", "Author Two"]`
|
||||
- **`date`**: ISO format in quotes `"YYYY-MM-DD"`
|
||||
- **`image`**: Path to featured image (relative to post directory)
|
||||
|
||||
### Social Media Cards
|
||||
|
||||
Use YAML anchors to avoid repeating the description:
|
||||
|
||||
```yaml
|
||||
description: &desc |
|
||||
Your description here that will be reused.
|
||||
|
||||
open-graph:
|
||||
description: *desc
|
||||
twitter-card:
|
||||
description: *desc
|
||||
```
|
||||
|
||||
The `&desc` creates an anchor, and `*desc` references it.
|
||||
|
||||
### Optional But Common Fields
|
||||
|
||||
- **`filters`**: Quarto filters to use
|
||||
- `shinylive` - For embedding Shinylive apps
|
||||
- `line-highlight` - For highlighting specific lines
|
||||
- **`engine`**: Quarto engine (`knitr`, `markdown`, `jupyter`)
|
||||
- **`freeze`**: Set to `true` if the post includes *any* computational output
|
||||
- **`format`**: HTML format options
|
||||
- `code-link: true` - Enable code linking
|
||||
- `anchor-sections: true` - Enable section anchors
|
||||
- `reference-location: document` or `section` - Where to place footnotes
|
||||
- **`code-annotations`**: Set to `hover` for hover annotations
|
||||
- **`editor`**: Editor options like `render-on-save: true`
|
||||
|
||||
### Image Options
|
||||
|
||||
Additional image control fields:
|
||||
|
||||
```yaml
|
||||
image: feature.svg
|
||||
imagealt: "Alternative text for image"
|
||||
image-header-disable: true # Don't show image in header
|
||||
```
|
||||
|
||||
### What's NOT Included
|
||||
|
||||
Unlike Tidyverse posts, Shiny posts do **not** include:
|
||||
|
||||
- `output: hugodown::hugo_document`
|
||||
- `slug` (filename determines URL)
|
||||
- `photo.url` and `photo.author` (different image structure)
|
||||
- Consistent `categories` field (optional, varies by post)
|
||||
|
||||
## Title Format
|
||||
|
||||
The main title can be flexible:
|
||||
|
||||
```markdown
|
||||
# packagename version
|
||||
```
|
||||
|
||||
Or more descriptive:
|
||||
|
||||
```markdown
|
||||
# Reintroducing the Shiny Extension for VS Code
|
||||
```
|
||||
|
||||
There's less rigid formatting for titles in Shiny posts.
|
||||
|
||||
## Lead Paragraphs
|
||||
|
||||
Shiny posts may use a lead paragraph div for emphasis:
|
||||
|
||||
```markdown
|
||||
::: lead
|
||||
**We're excited to announce the new Shiny extension for VS Code!**
|
||||
:::
|
||||
```
|
||||
|
||||
This creates a larger, emphasized opening paragraph.
|
||||
|
||||
## Code Formatting
|
||||
|
||||
### For Python Packages
|
||||
|
||||
Use bash code blocks for installation:
|
||||
|
||||
````markdown
|
||||
```bash
|
||||
pip install packagename
|
||||
```
|
||||
````
|
||||
|
||||
With extras:
|
||||
|
||||
````markdown
|
||||
```bash
|
||||
pip install "packagename[extra]"
|
||||
```
|
||||
````
|
||||
|
||||
### For R Packages
|
||||
|
||||
Use R code blocks:
|
||||
|
||||
````markdown
|
||||
```r
|
||||
install.packages("packagename")
|
||||
```
|
||||
````
|
||||
|
||||
For multiple packages:
|
||||
|
||||
````markdown
|
||||
```r
|
||||
install.packages(c("shiny", "bslib"))
|
||||
```
|
||||
````
|
||||
|
||||
### Code Block Attributes
|
||||
|
||||
Shiny posts use Quarto code block attributes:
|
||||
|
||||
````markdown
|
||||
```{.python filename="app.py"}
|
||||
from shiny import App
|
||||
|
||||
# code here
|
||||
```
|
||||
````
|
||||
|
||||
````markdown
|
||||
```{r install-bslib}
|
||||
#| eval: false
|
||||
install.packages("bslib")
|
||||
```
|
||||
````
|
||||
|
||||
### Line Highlighting
|
||||
|
||||
Use `# <<` comments to highlight lines (requires `line-highlight` filter):
|
||||
|
||||
````markdown
|
||||
```{.python filename="app.py"}
|
||||
from shiny.express import ui
|
||||
import shinyswatch
|
||||
|
||||
ui.page_opts(theme=shinyswatch.theme.darkly) # <<
|
||||
|
||||
# rest of code...
|
||||
```
|
||||
````
|
||||
|
||||
### Code Annotations
|
||||
|
||||
With `code-annotations: hover` in frontmatter, you can add annotations:
|
||||
|
||||
```python
|
||||
result = some_function() # <1>
|
||||
```
|
||||
|
||||
```markdown
|
||||
1. This annotation explains the line above
|
||||
```
|
||||
|
||||
## Tabsets for Multiple Variants
|
||||
|
||||
Shiny posts frequently use tabsets to show Express vs Core mode or Python vs R:
|
||||
|
||||
````markdown
|
||||
::: {.panel-tabset .shiny-mode-tabset group="shiny-app-mode"}
|
||||
#### Express
|
||||
|
||||
```{.python filename="app.py"}
|
||||
from shiny.express import ui
|
||||
# Express code
|
||||
```
|
||||
|
||||
#### Core
|
||||
|
||||
```{.python filename="app.py"}
|
||||
from shiny import ui
|
||||
# Core code
|
||||
```
|
||||
:::
|
||||
````
|
||||
|
||||
### Nested Tabsets
|
||||
|
||||
You can nest tabsets for Before/After within Express/Core:
|
||||
|
||||
````markdown
|
||||
::: {.panel-tabset group="shiny-app-mode"}
|
||||
#### Express
|
||||
|
||||
::: {.panel-tabset}
|
||||
##### Before
|
||||
|
||||
```python
|
||||
# old code
|
||||
```
|
||||
|
||||
##### After
|
||||
|
||||
```python
|
||||
# new code
|
||||
```
|
||||
:::
|
||||
|
||||
#### Core
|
||||
|
||||
::: {.panel-tabset}
|
||||
##### Before
|
||||
|
||||
```python
|
||||
# old code
|
||||
```
|
||||
|
||||
##### After
|
||||
|
||||
```python
|
||||
# new code
|
||||
```
|
||||
:::
|
||||
:::
|
||||
````
|
||||
|
||||
## Callouts
|
||||
|
||||
Quarto callouts for notes, tips, warnings:
|
||||
|
||||
```markdown
|
||||
::: {.callout-tip title="Writing brand.yml with the help of an LLM"}
|
||||
We know that writing YAML isn't everyone's cup of tea!
|
||||
...
|
||||
:::
|
||||
```
|
||||
|
||||
Types: `note`, `tip`, `warning`, `caution`, `important`
|
||||
|
||||
## Embedded Media
|
||||
|
||||
### Videos
|
||||
|
||||
````markdown
|
||||
::: column-page
|
||||
```{=html}
|
||||
<video controls>
|
||||
<source src="videos/demo.webm" type="video/webm">
|
||||
<source src="videos/demo.mp4" type="video/mp4">
|
||||
</video>
|
||||
```
|
||||
:::
|
||||
````
|
||||
|
||||
### Images with Attributes
|
||||
|
||||
```markdown
|
||||
{.shadow}
|
||||
```
|
||||
|
||||
Or with more attributes:
|
||||
|
||||
```markdown
|
||||
{fig-alt="Detailed alt text" fig-align="center" width="100%"}
|
||||
```
|
||||
|
||||
## Shinylive Examples
|
||||
|
||||
With the `shinylive` filter, you can embed live examples:
|
||||
|
||||
````markdown
|
||||
```{shinylive-python}
|
||||
#| standalone: true
|
||||
#| components: [editor, viewer]
|
||||
|
||||
## file: app.py
|
||||
from shiny.express import input, render, ui
|
||||
|
||||
# App code here
|
||||
```
|
||||
````
|
||||
|
||||
Or link to examples:
|
||||
|
||||
```markdown
|
||||
We've added a [complete branded theming example](https://shinylive.io/py/examples/#branded-theming) to shinylive.io.
|
||||
```
|
||||
|
||||
## Acknowledgements Section
|
||||
|
||||
Less consistent in Shiny posts. When present, variations include:
|
||||
|
||||
### Variation 1: Simple Thanks
|
||||
|
||||
```markdown
|
||||
## Thanks!
|
||||
|
||||
Thank you for trying out the Shiny extension for VS Code!
|
||||
If you find it helpful, please rate the extension on [the marketplace][Shiny extension].
|
||||
```
|
||||
|
||||
### Variation 2: Multiple Package Releases
|
||||
|
||||
```markdown
|
||||
## Release notes
|
||||
|
||||
**Big shout out to everyone involved!** 💙
|
||||
We'd want to extend a huge thank you to everyone who contributed pull requests, bug reports and feature requests.
|
||||
|
||||
#### bslib [v0.7.0](https://rstudio.github.io/bslib/news/index.html#bslib-070)
|
||||
|
||||
[List of contributors]
|
||||
|
||||
#### shiny [v1.8.1](https://shiny.posit.co/r/reference/shiny/1.8.1/upgrade.html)
|
||||
|
||||
[List of contributors]
|
||||
```
|
||||
|
||||
### Variation 3: Omitted
|
||||
|
||||
Some Shiny posts don't include acknowledgements, especially for announcements of tools rather than package releases.
|
||||
|
||||
### When Acknowledgements Are Included
|
||||
|
||||
Use similar format to Tidyverse:
|
||||
|
||||
```markdown
|
||||
## Acknowledgements
|
||||
|
||||
We'd like to thank everyone who contributed to this release:
|
||||
|
||||
[@user1](https://github.com/user1), [@user2](https://github.com/user2), and [@user3](https://github.com/user3).
|
||||
```
|
||||
|
||||
Or just reference the generator in code:
|
||||
|
||||
```markdown
|
||||
```{r}
|
||||
#| echo: false
|
||||
#| eval: false
|
||||
usethis::use_tidy_thanks("rstudio/bslib", from = "v0.6.1")
|
||||
```
|
||||
```
|
||||
|
||||
## CSS Customization
|
||||
|
||||
Shiny posts may include custom CSS in HTML blocks:
|
||||
|
||||
````markdown
|
||||
```{=html}
|
||||
<style>
|
||||
img { border-radius: 8px; }
|
||||
video {
|
||||
max-width: 100%;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
</style>
|
||||
```
|
||||
````
|
||||
|
||||
## Column Layouts
|
||||
|
||||
Use Quarto's column classes for wider content:
|
||||
|
||||
```markdown
|
||||
::: column-page
|
||||
[Wide content here]
|
||||
:::
|
||||
|
||||
::: column-body-outset
|
||||
[Slightly wider content]
|
||||
:::
|
||||
```
|
||||
|
||||
## Footnotes
|
||||
|
||||
Use standard markdown footnotes:
|
||||
|
||||
```markdown
|
||||
Text with a footnote[^footnote-key].
|
||||
|
||||
[^footnote-key]: This is the footnote text.
|
||||
```
|
||||
|
||||
With `reference-location: document` or `section` in frontmatter to control placement.
|
||||
|
||||
## Links and References
|
||||
|
||||
Define link references at the top or bottom of the file:
|
||||
|
||||
```markdown
|
||||
[brand.yml]: https://posit-dev.github.io/brand-yml
|
||||
[quarto]: https://quarto.org
|
||||
[shiny]: https://shiny.posit.co
|
||||
```
|
||||
|
||||
Then use them inline:
|
||||
|
||||
```markdown
|
||||
We're excited about [brand.yml] support!
|
||||
```
|
||||
|
||||
## Multi-Language Support (R and Python)
|
||||
|
||||
The Shiny blog often covers packages released for both R and Python (e.g., shiny, shinychat). Unlike Tidyverse posts which are language-specific, Shiny posts should show examples in both languages using Quarto tabsets.
|
||||
|
||||
### Use Tabsets Consistently
|
||||
|
||||
Every code example should include both R and Python variants using Quarto tabsets:
|
||||
|
||||
```markdown
|
||||
::: {.panel-tabset group="language"}
|
||||
## R
|
||||
|
||||
```r
|
||||
# R code here
|
||||
```
|
||||
|
||||
## Python
|
||||
|
||||
```python
|
||||
# Python code here
|
||||
```
|
||||
:::
|
||||
```
|
||||
|
||||
**Guidelines:**
|
||||
- Use `group="language"` to sync all language tabsets on the page
|
||||
- Provide equivalent functionality in both languages
|
||||
- Don't show R-only or Python-only examples unless the feature is language-specific
|
||||
- Keep examples parallel—if the R example shows 5 lines, the Python example should be similar
|
||||
|
||||
### Installation Instructions
|
||||
|
||||
Always show installation for both languages at the start of the post:
|
||||
|
||||
```markdown
|
||||
::: {.panel-tabset group="language"}
|
||||
## R
|
||||
|
||||
```r
|
||||
install.packages("packagename")
|
||||
```
|
||||
|
||||
## Python
|
||||
|
||||
```bash
|
||||
pip install packagename
|
||||
```
|
||||
:::
|
||||
```
|
||||
|
||||
### Language-Specific Features
|
||||
|
||||
When features differ between languages, be explicit about the differences:
|
||||
|
||||
```markdown
|
||||
::: {.panel-tabset group="language"}
|
||||
## R
|
||||
|
||||
In R, use `tool_annotations()` to customize display:
|
||||
|
||||
```r
|
||||
tool_annotations(title = "My Tool", icon = bsicons::bs_icon("star"))
|
||||
```
|
||||
|
||||
## Python
|
||||
|
||||
In Python, use the `._display` attribute:
|
||||
|
||||
```python
|
||||
my_tool._display = {"title": "My Tool", "icon": "star"}
|
||||
```
|
||||
:::
|
||||
```
|
||||
|
||||
### Version Information
|
||||
|
||||
Package versions often differ between R and Python. Be explicit:
|
||||
|
||||
- "Available in shinychat for R (v0.3.0) and shinychat for Python (v0.2.0 or later)"
|
||||
- Link to both language-specific documentation
|
||||
- Include separate release notes links:
|
||||
```markdown
|
||||
You can see the full list of changes in the [R release notes](url) and [Python release notes](url).
|
||||
```
|
||||
|
||||
### When to Use Multi-Language Tabsets
|
||||
|
||||
- **Always use** for packages that have both R and Python versions (shiny, shinychat, querychat, etc.)
|
||||
- **Don't use** for Python-only packages (shinyswatch) or R-only packages
|
||||
- **Don't use** for Tidyverse blog posts (which are built with hugodown/Hugo, not Quarto)
|
||||
|
||||
## Example Complete Frontmatter
|
||||
|
||||
### Python Package
|
||||
|
||||
```yaml
|
||||
---
|
||||
title: shinyswatch 0.7.0
|
||||
description: &desc Customizable shinyswatch themes and an improved theme picker round out shinyswatch v0.7.0.
|
||||
author: "Garrick Aden-Buie"
|
||||
date: "2024-07-19"
|
||||
|
||||
image: feature.jpg
|
||||
|
||||
open-graph:
|
||||
image: feature.jpg
|
||||
description: *desc
|
||||
twitter-card:
|
||||
image: feature.png
|
||||
description: *desc
|
||||
|
||||
filters:
|
||||
- line-highlight
|
||||
---
|
||||
```
|
||||
|
||||
### R Package with Full Options
|
||||
|
||||
```yaml
|
||||
---
|
||||
title: "Shiny for R updates: Extended tasks, JavaScript errors, and many bslib improvements"
|
||||
description: &desc |
|
||||
An overview of recent Shiny for R updates, including extended tasks, JavaScript errors, and many bslib improvements.
|
||||
author:
|
||||
- Carson Sievert
|
||||
date: "2024-03-27"
|
||||
|
||||
image: feature.png
|
||||
|
||||
open-graph:
|
||||
image: feature.png
|
||||
description: *desc
|
||||
twitter-card:
|
||||
image: feature.png
|
||||
description: *desc
|
||||
|
||||
editor:
|
||||
render-on-save: true
|
||||
|
||||
engine: knitr
|
||||
|
||||
filters:
|
||||
- shinylive
|
||||
|
||||
freeze: true
|
||||
|
||||
format:
|
||||
html:
|
||||
code-link: true
|
||||
anchor-sections: true
|
||||
reference-location: section
|
||||
|
||||
code-annotations: hover
|
||||
---
|
||||
```
|
||||
|
||||
## Examples of Well-Formatted Posts
|
||||
|
||||
Reference these posts for formatting examples:
|
||||
- [shinyswatch 0.7.0](https://shiny.posit.co/blog/posts/shinyswatch-0.7.0/)
|
||||
- [Shiny Extension for VS Code 1.0.0](https://shiny.posit.co/blog/posts/shiny-vscode-1.0.0/)
|
||||
- [Shiny for R 1.8.1](https://shiny.posit.co/blog/posts/shiny-r-1.8.1/)
|
||||
- [Branded theming for Shiny for Python](https://shiny.posit.co/blog/posts/shiny-python-1.2-brand-yml/)
|
||||
275
skills/release-post/references/tidyverse-formatting.md
Normal file
275
skills/release-post/references/tidyverse-formatting.md
Normal file
@@ -0,0 +1,275 @@
|
||||
# Tidyverse Blog Formatting Conventions
|
||||
|
||||
Tidyverse-specific formatting requirements for blog posts on tidyverse.org. These conventions are for the hugodown-based Tidyverse blog.
|
||||
|
||||
## Workflow for tidyverse.org Blog
|
||||
|
||||
When creating a blog post for the official `tidyverse/tidyverse.org` repository, follow these steps:
|
||||
|
||||
1. **Install hugodown** (if not already installed):
|
||||
```r
|
||||
pak::pkg_install("r-lib/hugodown")
|
||||
```
|
||||
|
||||
2. **Create a new post**:
|
||||
```r
|
||||
hugodown::use_tidy_post("short-name")
|
||||
```
|
||||
|
||||
This creates `content/blog/short-name/` containing an `index.Rmd` file.
|
||||
|
||||
Common patterns for `"short-name"`:
|
||||
- Package release: `lifecycle-1-0-0`, `parsnip-0-1-2`
|
||||
- Package release with specific topic: `dplyr-1-0-0-rowwise`, `parsnip-adjacent`, `dplyr-1-0-4-if-any`
|
||||
- Topic only: `self-cleaning-test-fixtures`, `taking-control-of-plot-scaling`
|
||||
|
||||
3. **Write and knit**:
|
||||
- Edit the generated `index.Rmd` file
|
||||
- Knit `index.Rmd` to generate `index.md`
|
||||
- Note: `.Rmd` files are only rendered when you explicitly knit them
|
||||
|
||||
4. **Preview the site**:
|
||||
```r
|
||||
hugodown::hugo_start()
|
||||
```
|
||||
This runs once per session and continues in the background to turn `.md` into `.html`.
|
||||
|
||||
5. **Check for outdated files** (if concerned):
|
||||
```r
|
||||
hugodown::site_outdated()
|
||||
```
|
||||
Lists all `.Rmd`s that need to be re-rendered.
|
||||
|
||||
6. **Add a photo**:
|
||||
Every blog post must be accompanied by a photo. If you don't have one in mind, try:
|
||||
- <https://unsplash.com>
|
||||
- <https://pexels.com>
|
||||
- Jenny Bryan's [free photo](https://github.com/jennybc/free-photos) link collection
|
||||
|
||||
7. **Submit PR**:
|
||||
- Every PR gets an automatic live preview via Netlify
|
||||
- Once merged, the preview becomes the live site
|
||||
|
||||
### Important Notes
|
||||
|
||||
- The site uses **hugodown** (not blogdown), which separates building into two steps:
|
||||
- hugodown generates `.md` from `.Rmd`
|
||||
- hugo generates `.html` from `.md`
|
||||
- Use `.Rmd` files (not `.Rmarkdown`)
|
||||
- Output should be `output: hugodown::hugo_document`
|
||||
- If updating an old post to use hugodown:
|
||||
- Rename from `.Rmarkdown` to `.Rmd`
|
||||
- Delete the `.markdown` file
|
||||
- Set `output: hugodown::hugo_document` in YAML metadata
|
||||
|
||||
### For Additional Context
|
||||
|
||||
If you need more details about the workflow or encounter issues, consult the `README.md` in the `tidyverse/tidyverse.org` repository.
|
||||
|
||||
## Frontmatter Format
|
||||
|
||||
Tidyverse blog posts use YAML frontmatter with this structure:
|
||||
|
||||
```yaml
|
||||
---
|
||||
output: hugodown::hugo_document
|
||||
slug: package-name-version
|
||||
title: package-name version
|
||||
date: YYYY-MM-DD
|
||||
author: Author Name
|
||||
description: >
|
||||
Brief description of the package and release
|
||||
photo:
|
||||
url: https://unsplash.com/photos/photo-id
|
||||
author: Photographer Name
|
||||
categories: [package-name]
|
||||
tags: [package-name, category]
|
||||
---
|
||||
```
|
||||
|
||||
### Required Fields
|
||||
|
||||
- **`output`**: Always `hugodown::hugo_document`
|
||||
- **`slug`**: URL slug using hyphens
|
||||
- Format: `packagename-x-y-z` (e.g., `ellmer-0-4-0`)
|
||||
- Replace dots with hyphens in version numbers
|
||||
- **`title`**: Display title with spaces
|
||||
- Format: `packagename x.y.z` (e.g., `ellmer 0.4.0`)
|
||||
- **`date`**: ISO format `YYYY-MM-DD`
|
||||
- **`author`**: Full name of primary author
|
||||
- **`description`**: Brief summary (can use `>` for multi-line)
|
||||
- **`photo`**: Featured image with attribution
|
||||
- `url`: Full URL to image (often Unsplash)
|
||||
- `author`: Photographer name for attribution
|
||||
- **`categories`**: Array with package name
|
||||
- **`tags`**: Array with package name and related tags
|
||||
|
||||
### Slug vs Title Convention
|
||||
|
||||
The slug is used in URLs and must be URL-safe:
|
||||
- Slug: `purrr-1-2-0` (hyphens, no dots)
|
||||
- Title: `purrr 1.2.0` (space, dots in version)
|
||||
|
||||
### Image Attribution
|
||||
|
||||
Featured images are typically from Unsplash with proper photographer attribution:
|
||||
|
||||
```yaml
|
||||
photo:
|
||||
url: https://unsplash.com/photos/abc123
|
||||
author: John Doe
|
||||
```
|
||||
|
||||
## Title Format
|
||||
|
||||
The main title uses a simple format with space between package name and version:
|
||||
|
||||
```markdown
|
||||
# packagename 1.2.0
|
||||
```
|
||||
|
||||
No "released" or "version" prefix. Just the package name and version number.
|
||||
|
||||
## Code Formatting
|
||||
|
||||
### Language Identifiers
|
||||
|
||||
Use triple backticks with `r` language identifier for R code:
|
||||
|
||||
````markdown
|
||||
```r
|
||||
library(packagename)
|
||||
|
||||
result <- function_name(
|
||||
arg1 = "value",
|
||||
arg2 = TRUE
|
||||
)
|
||||
```
|
||||
````
|
||||
|
||||
For installation:
|
||||
````markdown
|
||||
```r
|
||||
install.packages("packagename")
|
||||
```
|
||||
````
|
||||
|
||||
### Inline Code Elements
|
||||
|
||||
- Function names: `` `function()` ``
|
||||
- Packages: `` `{packagename}` `` when emphasizing it's a package
|
||||
- Arguments: `` `arg = value` ``
|
||||
- Values: `` `NULL` ``, `` `TRUE` ``, `` `"string"` ``
|
||||
|
||||
### Function Links
|
||||
|
||||
When linking to function documentation, use markdown links:
|
||||
|
||||
```markdown
|
||||
[`function_name()`](https://url-to-docs)
|
||||
```
|
||||
|
||||
## Section Structure
|
||||
|
||||
### Lifecycle Section Format
|
||||
|
||||
When including lifecycle changes, use this structure:
|
||||
|
||||
```markdown
|
||||
## Lifecycle changes
|
||||
|
||||
* **Fully removed** after 5+ years of deprecation:
|
||||
* `function1()` - use `replacement1()` instead
|
||||
* `function2()` - use `replacement2()` instead
|
||||
|
||||
* **Newly deprecated** (soft-deprecation):
|
||||
* `function3()` is superseded by `function4()`
|
||||
* `function5()` is no longer recommended
|
||||
|
||||
* **Breaking changes**:
|
||||
* Description of what changed and why
|
||||
```
|
||||
|
||||
Use bold for the lifecycle stage labels.
|
||||
|
||||
### Feature Sections
|
||||
|
||||
Use sentence case in headings:
|
||||
|
||||
```markdown
|
||||
## Easier `in_parallel()`
|
||||
|
||||
[Description of the feature...]
|
||||
```
|
||||
|
||||
Include function names in backticks when they're part of the heading.
|
||||
|
||||
## Acknowledgements Section
|
||||
|
||||
Always include as the final section:
|
||||
|
||||
```markdown
|
||||
## Acknowledgements
|
||||
|
||||
A big thank you to all the folks who helped make this release happen:
|
||||
|
||||
[@username1](https://github.com/username1), [@username2](https://github.com/username2), [@username3](https://github.com/username3), and [@username4](https://github.com/username4).
|
||||
```
|
||||
|
||||
### Formatting Rules
|
||||
|
||||
- Single paragraph format (not bulleted list)
|
||||
- GitHub handles as markdown links
|
||||
- Alphabetical order
|
||||
- Comma-separated with "and" before the last name
|
||||
- Period at the end
|
||||
|
||||
### Generating the List
|
||||
|
||||
Use `usethis::use_tidy_thanks()`:
|
||||
|
||||
```r
|
||||
# Fetch contributors since last release
|
||||
usethis::use_tidy_thanks("tidyverse/packagename")
|
||||
|
||||
# Or from specific tag
|
||||
usethis::use_tidy_thanks("tidyverse/packagename", from = "v1.0.0")
|
||||
```
|
||||
|
||||
This function outputs properly formatted markdown that can be copied directly into the blog post.
|
||||
|
||||
## Release Notes Link
|
||||
|
||||
Include a link to the full release notes (typically on pkgdown site):
|
||||
|
||||
```markdown
|
||||
You can see a full list of changes in the [release notes](https://packagename.tidyverse.org/news/).
|
||||
```
|
||||
|
||||
## Example Complete Frontmatter
|
||||
|
||||
```yaml
|
||||
---
|
||||
output: hugodown::hugo_document
|
||||
slug: purrr-1-2-0
|
||||
title: purrr 1.2.0
|
||||
date: 2025-11-04
|
||||
author: Hadley Wickham
|
||||
description: >
|
||||
purrr 1.2.0 includes deprecations and minor enhancements to
|
||||
functional programming tools in R.
|
||||
photo:
|
||||
url: https://unsplash.com/photos/xyz789
|
||||
author: Jane Photographer
|
||||
categories: [purrr]
|
||||
tags: [purrr, tidyverse]
|
||||
---
|
||||
```
|
||||
|
||||
## Examples of Well-Formatted Posts
|
||||
|
||||
Reference these posts for formatting examples:
|
||||
- [pkgdown 2.2.0](https://www.tidyverse.org/blog/2025/11/pkgdown-2-2-0/)
|
||||
- [testthat 3.3.0](https://www.tidyverse.org/blog/2025/11/testthat-3-3-0/)
|
||||
- [purrr 1.2.0](https://www.tidyverse.org/blog/2025/11/purrr-1-2-0/)
|
||||
- [ellmer 0.4.0](https://www.tidyverse.org/blog/2025/11/ellmer-0-4-0/)
|
||||
48
skills/release-post/scripts/get_contributors.R
Normal file
48
skills/release-post/scripts/get_contributors.R
Normal file
@@ -0,0 +1,48 @@
|
||||
#!/usr/bin/env Rscript
|
||||
# Fetch contributors for a package release using usethis::use_tidy_thanks()
|
||||
#
|
||||
# Usage:
|
||||
# Rscript get_contributors.R <repo> [<from>]
|
||||
#
|
||||
# Arguments:
|
||||
# repo: GitHub repository in "owner/repo" format (e.g., "tidyverse/dplyr")
|
||||
# from: Optional git ref (tag/SHA) to use as the starting point
|
||||
# If omitted, uses the previous release
|
||||
#
|
||||
# Output:
|
||||
# Markdown-formatted list of contributors suitable for blog post acknowledgments
|
||||
#
|
||||
# Examples:
|
||||
# Rscript get_contributors.R "tidyverse/dplyr"
|
||||
# Rscript get_contributors.R "tidyverse/dplyr" "v1.0.0"
|
||||
|
||||
args <- commandArgs(trailingOnly = TRUE)
|
||||
|
||||
if (length(args) == 0) {
|
||||
cat("Error: Repository argument required\n")
|
||||
cat("Usage: Rscript get_contributors.R <repo> [<from>]\n")
|
||||
cat("Example: Rscript get_contributors.R 'tidyverse/dplyr'\n")
|
||||
quit(status = 1)
|
||||
}
|
||||
|
||||
repo <- args[1]
|
||||
from <- if (length(args) >= 2) args[2] else NULL
|
||||
|
||||
# Check if usethis is installed
|
||||
if (!requireNamespace("usethis", quietly = TRUE)) {
|
||||
cat("Error: usethis package is not installed\n")
|
||||
cat("Install it with: install.packages('usethis')\n")
|
||||
quit(status = 1)
|
||||
}
|
||||
|
||||
# Fetch contributors
|
||||
cat("Fetching contributors for", repo, "...\n\n")
|
||||
|
||||
if (is.null(from)) {
|
||||
contributors <- usethis::use_tidy_thanks(repo)
|
||||
} else {
|
||||
contributors <- usethis::use_tidy_thanks(repo, from = from)
|
||||
}
|
||||
|
||||
# The function prints the result to console
|
||||
# No additional output needed
|
||||
Reference in New Issue
Block a user