type: decision
status: active
timestamp: 2026-06-21
tags: [decision, package, omni-publish, automation, blogging, cross-posting]

@chirag127/omni-publish package — auto-blog releases to 8+ platforms

@chirag127/omni-publish handles auto-publishing releases notes / blog posts to dev.to + hashnode + medium + X + LinkedIn + Bluesky + Mastodon\ + Reddit on tag push or release create. Triggered by GitHub Actions reusable workflow\ per repo. Platforms are env-gated — if DEVTO_API_KEY isn't set globally,\ dev.to is skipped automatically. Lives alongside the existing oriz-omni-post-app\ (the orchestrator UI / catalog of cross-posts).

@chirag127/omni-publish — auto-blog package

Decision

A new npm package @chirag127/omni-publish (v0.1.0 published 2026-06-21) handles auto-publishing release notes, blog posts, or changelog entries to multiple platforms on tag push or release create. Lives at:

The existing oriz-omni-post-app (repos/oriz/own/prod/apps/content/oriz-omni-post-app/) stays — it’s the orchestrator + UI + catalog of past cross-posts. The new package is the engine that the app (and any GitHub Actions workflow) calls.

Platforms supported

In priority order:

  1. dev.toDEVTO_API_KEY env var; uses dev.to REST API (/api/articles)
  2. HashnodeHASHNODE_API_KEY + HASHNODE_PUBLICATION_ID
  3. X / TwitterX_API_KEY + X_API_SECRET + X_ACCESS_TOKEN + X_ACCESS_SECRET
  4. LinkedInLINKEDIN_ACCESS_TOKEN
  5. BlueskyBLUESKY_HANDLE + BLUESKY_APP_PASSWORD (AT Protocol)
  6. MastodonMASTODON_INSTANCE + MASTODON_ACCESS_TOKEN
  7. RedditREDDIT_CLIENT_ID + REDDIT_CLIENT_SECRET + REDDIT_USERNAME + REDDIT_PASSWORD
  8. MediumMEDIUM_INTEGRATION_TOKEN (Medium deprecated integration tokens but the API still works for some accounts)

Platforms are env-gated: if a platform’s env vars are not set, that platform is silently skipped. So adding a platform is just adding env vars at the chirag127 org level.

How it triggers per repo

Each repo’s .github/workflows/release.yml calls:

- name: Cross-post release
  if: github.event_name == 'release'
  uses: chirag127/omni-publish-npm-pkg/.github/workflows/cross-post.yml@main
  with:
    title: "${{ github.event.release.name }}"
    body: "${{ github.event.release.body }}"
    canonical_url: "${{ github.event.release.html_url }}"
  secrets: inherit

Or directly via npm bin in a workflow step:

- run: npx @chirag127/omni-publish --title "$TITLE" --body "$BODY" --canonical "$URL"
  env:
    DEVTO_API_KEY: ${{ secrets.DEVTO_API_KEY }}
    HASHNODE_API_KEY: ${{ secrets.HASHNODE_API_KEY }}
    # ... rest of platform tokens

Why this shape (package + app)

Two artefacts because they do different things:

Per [[cross-post-engine]] the existing decision already named the family pattern. This decision adds the package boundary so the engine becomes reusable while the orchestrator stays family-internal.

Versioning

Cross-platform retry + scheduling deferred to v0.2+. v0.x is fire-and-forget per platform.

v0.1.1 shipped (2026-06-21)

5 auto-publish adapters (each env-gated)

PlatformRequired env vars
dev.toDEVTO_API_KEY
HashnodeHASHNODE_API_KEY + HASHNODE_PUBLICATION_ID
BlueskyBLUESKY_HANDLE + BLUESKY_APP_PASSWORD (uses @atproto/api)
MastodonMASTODON_INSTANCE + MASTODON_ACCESS_TOKEN
Threads (Meta)THREADS_ACCESS_TOKEN (2-step create + publish)

4 manual-platform drafts via Telegram

For X, Reddit, LinkedIn, Medium — omni-publish generates per-platform AI-rewritten drafts and posts them to a Telegram channel for the user to review + post by hand.

Reusable workflow

chirag127/omni-publish-npm-pkg/.github/workflows/cross-post.yml@main — any repo can call it with secrets: inherit.

Bin entry

v0.1.1 fixes the v0.1.0 bin bug by shipping a plain ESM bin/omni-publish.mjs (no TypeScript at runtime). Requires Node 22+ for native fetch. npx @chirag127/omni-publish now works.

v0.1.2 — 2026-06-22

Added 4-channel routing and dual-write drafts.

New adapters

New types — PublishRoutes

export type PublishRoutes = {
  announce?: boolean // default true  ? @oriz_announcements
  drafts?: boolean   // default true  ? @oriz_drafts + chirag127/oriz-drafts Issues (dual-write)
  paisa?: boolean    // default false ? @oriz_paisa (also auto-on if tags include 'paisa' / 'finance')
}

Pass via publish({ ..., routes: { ... } }). The CLI also reads OMNI_ANNOUNCE / OMNI_DRAFTS / OMNI_PAISA env vars.

Dual-write drafts

The drafts route now writes to BOTH Telegram (4 per-platform messages) AND a GitHub Issue in chirag127/oriz-drafts, in parallel via Promise.all. Either backend failing is logged but does not fail the overall publish.

New env vars (v0.1.2)

Env varPurpose
TELEGRAM_BOT_TOKENBot token for all Telegram channels. Falls back to TELEGRAM_DRAFTS_BOT_TOKEN (legacy).
TELEGRAM_ANNOUNCE_CHAT_IDPublic @oriz_announcements channel id.
TELEGRAM_DRAFTS_CHAT_IDPrivate @oriz_drafts channel id (manual-platform queue, unchanged).
TELEGRAM_OPS_CHAT_IDPrivate @oriz_ops channel id (CI / mirror / health — reserved).
TELEGRAM_PAISA_CHAT_IDPublic @oriz_paisa channel id (finance content, opt-in).
OMNI_DRAFTS_GH_PATGitHub PAT for chirag127/oriz-drafts Issues dual-write.
OMNI_ANNOUNCE / OMNI_DRAFTS / OMNI_PAISAWorkflow-level route toggles consumed by the CLI.

Reusable workflow

.github/workflows/cross-post.yml now exposes announce / drafts / paisa boolean inputs and forwards every new Telegram chat id + OMNI_DRAFTS_GH_PAT secret.

Cross-refs


Edit on GitHub · Back to index