Official CLI
Publish or update Markdown articles from your local terminal.
Publish or update Markdown articles from the ZyVOP CLI, a CI/CD workflow, or the REST API, with optional delivery to supported connected platforms.
Publish or update Markdown articles from your local terminal.
Use one authenticated endpoint to create or update an article.
Publish tracked Markdown files through GitHub Actions or other automation.
The official command-line interface for ZyVOP. Write in standard Markdown with YAML frontmatter, publish to ZyVOP, and optionally deliver to Dev.to, Hashnode, Medium, WordPress, and Bluesky from your terminal or CI/CD pipeline.
# Run without a global installation
npx zyvop --help
# Publish and cross-post an article
npx zyvop publish ./my-article.mdUse a personal developer token for REST publishing and CI/CD. Interactive login stores a user-session token for session-backed commands such as back-catalog import:
# Recommended for publishing and CI/CD
zyvop login --token zv_0123456789abcdef0123456789abcdef0123456789abcdef
# Or provide the developer token through the environment
export ZYVOP_TOKEN="zv_0123456789abcdef0123456789abcdef0123456789abcdef"
# Interactive user-session login (required by import)
zyvop login
# Inspect the stored authentication and endpoint
zyvop whoami
# Clear stored credentials on this machine
zyvop logoutPublish to ZyVOP and request delivery to the enabled connected destinations. External delivery runs in the background. Use --dry-run to check local parsing and relative asset resolution first:
# Local dry-run preview: validates markdown without contacting servers or publishing
zyvop publish ./my-article.md --dry-run --base-url https://myblog.com/
# Publish article live and cross-post to all enabled syndication targets
zyvop publish ./my-article.md
# Publish as a private draft with custom overrides
zyvop publish ./my-article.md --draft --tags "nextjs,react,typescript"Place standard YAML frontmatter at the top of your .md file to configure syndication targets, canonical URLs, and article metadata:
---
title: Building Scalable Microservices with Go
subtitle: A practical deep-dive into distributed architecture
tags: [golang, backend, docker, microservices]
canonical_url: https://myblog.com/go-microservices
base_url: https://myblog.com/
category: backend
cover_image: /images/go-architecture.webp
generate_toc: true
cross_post:
devto: true
hashnode: true
medium: true
bluesky: true
wordpress: true
---
# 1. Introduction
Write your technical article here in Markdown with full support for tables, code snippets, and diagrams...All options available when executing zyvop publish <file>:
| Flag | Type | Description | Default |
|---|---|---|---|
| -d, --dry-run | boolean | Validate and preview the local payload without authentication, network requests, or publishing | false |
| --base-url <url> | string (URL) | Base URL for resolving root-relative (/img.png) or file-relative (./img.png) cover and body images | canonical_url origin |
| --title <title> | string | Override article title specified in YAML frontmatter | Frontmatter title |
| --subtitle <subtitle> | string | Short subtitle, subtitle summary, or SEO description (max 200 chars) | Frontmatter subtitle |
| --tags <tags> | string (comma-separated) | Override discovery tags (e.g. "react,nextjs,typescript") | Frontmatter tags |
| --category <slug> | string (slug) | Target topic category slug (e.g. "frontend", "backend", "devops", "ai") | Frontmatter category |
| --series <seriesId> | string (ID) | Attach the article to an existing ZyVOP series | Frontmatter series ID |
| --canonical <url> | string (URL) | Canonical URL used to signal the preferred source to search engines | Not set |
| --cover <url> | string (URL/path) | Cover image URL or relative image path | Frontmatter cover |
| --draft | boolean | Save the article as a ZyVOP draft without external delivery | false |
| --toc | boolean | Automatically generate and render a floating Table of Contents | Frontmatter toc |
| --devto / --no-devto | boolean | Explicitly enable or disable syndication to dev.to | true (if connected) |
| --hashnode / --no-hashnode | boolean | Explicitly enable or disable syndication to Hashnode | true (if connected) |
| --medium / --no-medium | boolean | Explicitly enable or disable syndication to Medium | false |
| --bluesky / --no-bluesky | boolean | Broadcast published link and excerpt to Bluesky timeline | false |
| --wordpress | boolean | Enable cross-posting to connected WordPress site | false |
| -t, --token <token> | string | ZyVOP token supplied directly for this command | ZYVOP_TOKEN, then stored token |
| --endpoint <url> | string (URL) | Advanced custom GraphQL endpoint for testing or another deployment | https://zyvop.com/graphql |
| Field | Type | Description | Default |
|---|---|---|---|
| title | string | The main headline for your article | Markdown filename |
| subtitle | string | Optional article subtitle | - |
| excerpt | string | Optional card preview and summary text | Auto-generated |
| tags | string[] | string | Topics and discovery tags (e.g. [react, nextjs] or comma-separated string) | [] |
| canonical_url | string | Original source URL for canonical reference across syndication targets | Not set |
| base_url | string | Base domain for resolving site-relative cover and content images (e.g. https://myblog.com) | Inferred from canonical_url |
| category | string | Category slug (e.g. frontend, backend, devops, ai) | - |
| cover_image | string | Public image URL or relative path (e.g. /blog/cover.webp) | - |
| generate_toc | boolean | Automatically generate floating Table of Contents | false |
| comments_enabled | boolean | Enable reader comments and discussion on this post | true |
| cross_post | object | Delivery flags: devto, hashnode, medium, wordpress, and bluesky | Dev.to and Hashnode enabled |
| zyvop_id / id / slug | string | Stable ZyVOP identifier used for predictable repeat updates | - |
| series_id | string | ID of an existing ZyVOP series | - |
| published / draft | boolean | Set published: false or draft: true to save as draft | published: true |
| status | string | Explicit publication status: DRAFT, PUBLISHED, or SCHEDULED | PUBLISHED |
| scheduled_at | string | ISO 8601 timestamp for scheduling publication in the future | - |
layout, readingTime, featured) are safely preserved in your repository and ignored by ZyVOP without schema errors./blog/cover.webp) and file-relative (./cover.webp) cover and body images are automatically resolved into absolute URLs using base_url or canonical_url.zyvop_id, id, slug, or canonical_url in frontmatter. The API can then match an article you own and update it instead of creating another post.Import a back catalog from Dev.to, Hashnode, Medium, or an RSS feed. This command uses the session-backed GraphQL flow, so sign in interactively before running it:
# Import all published articles from Dev.to
zyvop import devto your_devto_username
# Import all articles from Hashnode
zyvop import hashnode yourblog.hashnode.dev
# Import a Medium publication
zyvop import medium @your_medium_username
# Import a public RSS feed
zyvop import rss https://example.com/feed.xml
# Verify current authentication session
zyvop whoamiA personal zv_ developer token authenticates REST publishing but does not authenticate this GraphQL-backed import command.
Keep articles in Git and publish changed Markdown files to ZyVOP with a personal developer token. Enabled external destinations are handled after an eligible article is published.
name: Publish to ZyVOP
on:
push:
branches: [main]
paths:
- 'posts/**/*.md'
permissions:
contents: read
concurrency:
group: zyvop-publish-${{ github.ref }}
cancel-in-progress: false
jobs:
publish:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 20
- name: Publish Modified Markdown Posts via ZyVOP CLI
env:
ZYVOP_TOKEN: ${{ secrets.ZYVOP_TOKEN }}
run: |
set -euo pipefail
before="${{ github.event.before }}"
after="${{ github.sha }}"
if [[ "$before" =~ ^0+$ ]] || ! git cat-file -e "$before^{commit}" 2>/dev/null; then
mapfile -d '' files < <(git ls-files -z -- ':(glob)posts/**/*.md')
else
mapfile -d '' files < <(
git diff --name-only -z --diff-filter=ACMR "$before" "$after" -- ':(glob)posts/**/*.md'
)
fi
if (( ${#files[@]} == 0 )); then
echo "No Markdown files modified."
exit 0
fi
for file in "${files[@]}"; do
if [ -f "$file" ]; then
echo "Deploying $file..."
npx --yes zyvop@1 publish "$file"
fi
donezyvop_id, slug, or stable canonical_url in each file so repeat runs can match the article you own.The public developer-token API currently provides one endpoint for creating or updating an article from Markdown with YAML frontmatter.
Authorization: Bearer zv_.... Generate or revoke the token from your ZyVOP settings.POST https://zyvop.com/api/v1/articles
Content-Type: application/json
Authorization: Bearer <your_developer_token>Send the complete Markdown document in the JSON content field. The API also accepts markdown as the field name.
{
"content": "---
title: My Automated Post
tags: [api, automation]
canonical_url: https://example.com/posts/automated
cross_post:
devto: true
hashnode: true
medium: false
wordpress: false
bluesky: false
---
# Hello World
Published with the ZyVOP REST API."
}The response reports whether ZyVOP created or updated the article.
{
"success": true,
"action": "created",
"data": {
"id": "9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d",
"slug": "my-automated-post-72gpx",
"status": "PUBLISHED",
"url": "https://zyvop.com/my-automated-post-72gpx"
}
}id, slug, or canonical_url so the API can match an existing article owned by the token's user. Otherwise, the server may create a new article.REST frontmatter can request Dev.to, Hashnode, Medium, and WordPress article publishing or Bluesky social promotion. The corresponding integration must be connected, the article must be eligible for promotion, and delivery runs in the background. Mastodon is not currently accepted by this REST endpoint.
429 Too Many Requests with rate-limit headers.Join the developer Discord to discuss the CLI and REST API, suggest improvements, report issues, and talk with other technical writers.
Generate a personal developer token, connect the destinations you use, and publish Markdown from your terminal or CI workflow.