feat: Notes content type + Bluesky POSSE syndication#366
feat: Notes content type + Bluesky POSSE syndication#366byte-the-bot wants to merge 6 commits intomainfrom
Conversation
| - name: Find unpublished notes | ||
| id: find | ||
| run: | | ||
| unpublished="" | ||
| for file in notes/*.md; do | ||
| if [ -f "$file" ]; then | ||
| if ! grep -q "bsky_url:" "$file"; then | ||
| # Check if date is >= 2026-03-01 | ||
| date_line=$(grep "^date:" "$file" | head -1) | ||
| if [ -n "$date_line" ]; then | ||
| post_date=$(echo "$date_line" | sed 's/date: //') | ||
| if [[ "$post_date" > "2026-02-28" ]] || [[ "$post_date" == "2026-03-01" ]]; then | ||
| unpublished="$unpublished $file" | ||
| fi | ||
| fi | ||
| fi | ||
| fi | ||
| done | ||
|
|
||
| unpublished=$(echo "$unpublished" | xargs) | ||
| echo "paths=$unpublished" >> $GITHUB_OUTPUT | ||
|
|
||
| if [ -n "$unpublished" ]; then | ||
| echo "Found unpublished notes: $unpublished" | ||
| else | ||
| echo "No unpublished notes found" | ||
| fi |
There was a problem hiding this comment.
Can we fold all this into a cli command too
There was a problem hiding this comment.
Addressed in 74b3ad5 — the find-unpublished-notes shell logic has been folded into the CLI. The command now takes --dir and handles scanning for unpublished notes internally. The workflow just calls ./target/release/server publish-bluesky --dir notes.
|
|
||
| /// Format the post text for Bluesky, truncating body if needed to stay within 300 chars | ||
| fn format_post_text(title: &str, body: &str, url: &str) -> String { | ||
| // Format: "{title}\n\n{body}\n\n{url}" |
There was a problem hiding this comment.
I think I want to leave the url off.
And is title optional? or I think I want a way to hide the title from bluesky optionally if its not
There was a problem hiding this comment.
Addressed in 74b3ad5 — URL is removed from the post text (the website card embed handles linking instead). Title is included by default but can be hidden by setting bsky_hide_title: true in the note's frontmatter.
| if content.contains("bsky_url:") { | ||
| println!("Note already has bsky_url, skipping: {}", path.display()); | ||
| return Ok(()); | ||
| } |
There was a problem hiding this comment.
Lets do this check after we parse the frontmatter
There was a problem hiding this comment.
Addressed in 74b3ad5 — the string-based content.contains("bsky_url:") pre-parse check has been removed. The idempotency check now happens after parsing frontmatter via frontmatter.bsky_url.is_some() in find_unpublished_notes.
Test scaffolds for notes content type + Bluesky syndication: - posts/src/notes.rs: NoteKind enum, FrontMatter with optional kind/bsky_url, NotePosts loading - server/src/bluesky.rs: AT URI to web URL conversion, facet byte offsets, serialization - server/src/commands/bluesky.rs: frontmatter parsing, strip_markdown, format_post_text, update_frontmatter All tests use #[ignore] since the production types don't exist yet.
…cation Migrate 15 TIL files to notes/ with optional kind field (til, link). Add permanent redirects from /til/* to /notes/*. Create Bluesky API client for POSSE syndication with publish-bluesky CLI command and GitHub Actions workflow for automated posting on deploy. Implements BLOG-6a79edf75fad4d29
Leave markdown formatting as-is when posting notes to Bluesky rather than stripping bold, italic, backticks, headings, and links. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
0c4a64d to
9af24c6
Compare
…parsed frontmatter for idempotency - Add strip_markdown() to remove markdown formatting before posting to Bluesky - Fix build_link_facets to track search position, avoiding wrong offsets for duplicate URLs - Use parsed frontmatter.bsky_url.is_some() instead of raw string search for idempotency check - Add tests for strip_markdown and duplicate URL facet offsets Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Only convert [text](url) -> text in Bluesky posts. Leave all other markdown formatting (bold, italic, backticks, headings) as-is. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Summary
kindfield (til,link)notes/withkind: tiland adds permanent/til/*→/notes/*redirectspublish-blueskyCLI command for POSSE syndication with idempotency viabsky_urlfrontmatter fieldbsky_urlis presentTest plan
cargo test -p posts— 17 tests pass (notes module, migration verification)cargo test -p server bluesky— 31 tests pass (API client, CLI command, facets, formatting)cargo test -p server test::validate— 1 test passes (content validation)cargo clippy -- -D warnings— cleancargo fmt --check— clean/til/routes redirect to/notes/in browserpublish-blueskywith real Bluesky credentialsImplements BLOG-6a79edf75fad4d29
🤖 Generated with Claude Code