Skip to content

feat(marketing/channels): Dev.to adapter#435

Merged
blove merged 10 commits into
mainfrom
marketing-channel-devto
May 18, 2026
Merged

feat(marketing/channels): Dev.to adapter#435
blove merged 10 commits into
mainfrom
marketing-channel-devto

Conversation

@blove
Copy link
Copy Markdown
Contributor

@blove blove commented May 18, 2026

Summary

Follow-up to PR #425 (X channel adapter). Implements the Dev.to adapter behind the same ChannelAdapter interface.

Changes:

  • Extends Draft with optional article: DraftArticle (title, tags, canonicalUrl, description). Future LinkedIn long-form posts will reuse this shape.
  • New DevToAdapter class: single API key auth (DEVTO_API_KEY), single POST endpoint, real metrics() (Dev.to's read API is free).
  • post() publishes immediately (published: true) — Cowork approval is the human gate.
  • metrics() maps Dev.to fields → `PostMetrics` (impressions, replies, shares; clicks unavailable).
  • Validation enforces Dev.to tag rules (`^[a-z0-9]+$`, ≤ 4 tags, ≤ 30 chars), 1-128 char title, https-only canonical URL.

Tests: 60/60 across 7 spec files (33 X + 27 Dev.to). All msw-mocked.

Build artifacts:

  • `npx nx run marketing-channels:build` green
  • `npx nx run marketing-channels:test` green (60 tests)
  • `npx nx run website:build` green
  • `DRY_RUN=1 pnpm marketing:channels:devto:smoke` green

Known follow-up (not blocking this PR):

  • `DevToAdapter` constructor throws on missing `DEVTO_API_KEY` before the dry-run guard in `postDevTo`, so dry-run requires a placeholder value in `.env`. Same architectural pattern as `XAdapter`. Worth a tiny refactor to short-circuit env requirements when `DRY_RUN=1`. Filing as a follow-up rather than expanding this PR's scope.

Manual smoke required before merge:

  • Get a Dev.to API key at https://dev.to/settings/extensions, paste `DEVTO_API_KEY=` into `.env`
  • Run: `pnpm marketing:channels:devto:smoke`
  • Confirm the post lands on Dev.to, then delete it

Spec: `docs/superpowers/specs/marketing/2026-05-17-channel-adapter-devto-design.md`
Plan: `docs/superpowers/plans/marketing/2026-05-17-channel-adapter-devto.md`

Test plan

  • Build green
  • Tests green (60/60)
  • Website build green
  • Dry-run smoke green
  • Brian runs live Dev.to smoke; result pasted below

🤖 Generated with Claude Code

blove and others added 10 commits May 18, 2026 12:26
Follow-up to channel-adapters. Extends Draft with optional
DraftArticle (title, tags, canonicalUrl, description) — usable by
Dev.to v1 and LinkedIn long-form later. Single API key auth, single
POST endpoint, real metrics() (Dev.to read API is free). Direct
syndication of blog posts with canonical_url set to cacheplane.ai/blog.
Publishes immediately (Cowork is the human gate).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
10 tasks across 5 phases: extend Draft with DraftArticle, add Dev.to
validation rules (TDD), implement post() and metrics() with msw mocks,
DevToAdapter class, wire registry, extend smoke script, README +
MANUAL-SMOKE updates, build/test verification, PR (stacked on #425).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@vercel
Copy link
Copy Markdown

vercel Bot commented May 18, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
cacheplane Ready Ready Preview, Comment May 18, 2026 7:47pm

Request Review

@blove
Copy link
Copy Markdown
Contributor Author

blove commented May 18, 2026

Live smoke ✅

Ran pnpm marketing:channels:devto:smoke against Brian's Dev.to account.

{
  "channel": "devto",
  "postId": "3695562",
  "url": "https://dev.to/blove/marketing-pipeline-smoke-test-2026-05-18t195042132z-46gl",
  "postedAt": "2026-05-18T19:50:42Z"
}

Metrics: {
  "postId": "3695562",
  "impressions": 0,
  "replies": 0,
  "shares": 0,
  "fetchedAt": "2026-05-18T19:50:47.715Z"
}

Both post() and metrics() work end-to-end against the live API. Counts are 0 because the article is fresh; field mapping is correct. Test article will be deleted from Dev.to. Auto-merge enabled.

@blove blove merged commit 6f80043 into main May 18, 2026
18 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant