DEV Community

Cover image for πŸ“ Dev.to Writers Community: One Command to Maintain Them All
Benoit COUETIL πŸ’« for Zenika

Posted on • Edited on

πŸ“ Dev.to Writers Community: One Command to Maintain Them All

DEV Weekend Challenge: Community

This is a submission for the DEV Weekend Challenge: Community

The Community

The people writing technical articles right here on dev.to β€” the ones who keep a folder full of markdown files and occasionally wonder why they didn't just use the browser editor. Occasionally. If you're curious why plain text won, we dig into that in Documentation-as-Code Has Silently Won For Tech Content.

What I Built

A fork of devto-cli β€” a Node.js CLI that turns local markdown files into dev.to articles. The original tool by Yohan Lasorsa handles article creation, push to dev.to via the API, stats, GitHub-hosted images with automatic URL rewriting, and a GitHub Action for automated publishing.

I just kept running into small things it didn't cover, so I forked it and added a bunch of features. Here's what came out.

Demo

Content enrichment

Diagrams as code with Kroki

Write a diagram in your markdown:

<!-- diagram-name: shell-runner-well-sized-before-optimization -->
'''mermaid
%%{init: {'theme':'forest'}}%%
gantt
    title Shell Executor - Well-Sized Server (Before Extreme Optimization)
    dateFormat X
    axisFormat %s
    section Waiting
    Sufficient capacity                    :active, wait, 0, 1s
    section Server
    Resource allocation                    :active, prep, after wait, 1s
    section OS
    Native system (no container)           :active, env, after prep, 1s
    section Source Code
    Git fetch (local reuse)                :active, git, after env, 2s
    section Cache
    Restore (local filesystem)             :active, cache, after git, 2s
    section Artifacts
    Download artifacts                     :done, art, after cache, 3s
    section Execution
    Scripts                                :done, exec, after art, 10s
    section Termination
    Upload cache (local)                   :active, save1, after exec, 1s
    Upload artifacts (GitLab network)      :done, save2, after save1, 4s
'''
Enter fullscreen mode Exit fullscreen mode

Run:

dev diaggen my-article.md
Enter fullscreen mode Exit fullscreen mode

Diagram

The CLI sends the block to Kroki, gets back an image, and saves it locally. After committing the image to your assets repo, dev push replaces the code block with an image link pointing to GitHub β€” dev.to never sees the mermaid source. But your local source is preserved, letting you fix the diagram when needed. Supports mermaid, PlantUML, BlockDiag, and many others.

See 13 diagrams generated this way in GitLab Runners: Which Topology for Fastest Job Execution?

Charts from CSV data

dev.to has no native chart support. Describe a chart as CSV inside a `chart block β€” first line is chart type and options, then data rows. Category charts (bar, line, area…) use a header row starting with x; pie, donut, and gauge use one name,value row per slice.

Run dev diaggen to render PNGs locally, commit them to GitHub, then dev push β€” same workflow as Kroki diagrams. The blocks below are live: they stay as source in this file and become images on dev.to at push time.

Supported chart types (C3.js): line, spline, step, area, area-spline, area-step, bar, scatter, pie, donut, gauge. Add stacked=true on bar for percentage stacked bars. Options: x-type=category, x-label, y-label, y-range=min_max, data-labels=true, width, height, horizontal=true, x-tick-angle, legend=bottom, order=desc. (scatter requires paired x/y columns β€” not yet supported by the CSV format.)

Five live examples below β€” close variants are grouped rather than repeated. Each uses several data rows (one per series):

bar β€” grouped bars (and stacked=true)

Swap in stacked=true on the first line for percentage stacked bars.

Diagram

line, spline, step β€” trends over time

Same CSV β€” only the type token changes. Shown here as spline; use line for straight segments or step for stairs.

Diagram

area, area-spline β€” filled curves

Same CSV β€” swap area-spline for area to drop smoothing. Three series below.

Diagram

pie, donut β€” part-of-whole

Same name,value rows β€” swap pie for donut on the first line. One row per slice.

Diagram

gauge β€” single KPI

Gauge charts accept one value β€” the exception to the multi-row pattern.

Diagram

Automatic table of contents

Add two markers anywhere in your article:

`markdown

`

Then:

`bash
dev push --update-toc my-article.md
`

The CLI scans headings and generates anchored links between the markers. The current article uses it.

ANSI-styled terminal output

Choosing colors in a displayed log is a must. The CLI converts a simple pseudo-ANSI syntax into styled HTML blocks.

In your markdown, use {{TAG}} to start a color. The {{/}} closing tag is optional β€” without it, the color continues until the next tag or end of block. This means multiline content stays colored naturally:

`markdown
'''ansi
{{RED}}The quick brown fox{{BOLD_RED}} jumps over the lazy dog
{{GREEN}}The quick brown fox{{BOLD_GREEN}} jumps over the lazy dog
{{YELLOW}}The quick brown fox{{BOLD_YELLOW}} jumps over the lazy dog
{{ORANGE}}The quick brown fox{{BOLD_ORANGE}} jumps over the lazy dog
{{BLUE}}The quick brown fox
{{BOLD_BLUE}}jumps over the lazy dog
{{MAGENTA}}The quick brown fox{{BOLD_MAGENTA}} jumps over the lazy dog
{{CYAN}}The quick brown fox{{BOLD_CYAN}} jumps over the lazy dog
{{WHITE}}The quick brown fox{{BOLD_WHITE}} jumps over the lazy dog
{{GRAY}}The quick brown fox{{BOLD_GRAY}} jumps over the lazy dog
{{BG_RED}}The quick brown fox{{/}} jumps over the lazy dog
{{BG_GREEN}}The quick brown fox{{BG_YELLOW}} jumps over the lazy dog
{{BG_ORANGE}}The quick brown fox
jumps over the lazy dog
{{BG_BLUE}}The quick brown fox{{BG_MAGENTA}} jumps over the lazy dog
{{BG_CYAN}}The quick brown fox{{BG_WHITE}} jumps over the lazy dog
{{BG_GRAY}}The quick brown fox{{/}} jumps over the lazy dog
'''
`

After dev push, this renders as a properly colored terminal block on dev.to β€” 9 base colors Γ— 3 variants (plain, bold, background). No closing tag needed: colors flow until the next tag, even across lines. All colors are overridable via .env variables (ANSI_RED=#ff6161, etc.).

The quick brown fox jumps over the lazy dog
The quick brown fox jumps over the lazy dog
The quick brown fox jumps over the lazy dog
The quick brown fox jumps over the lazy dog
The quick brown fox
jumps over the lazy dog
The quick brown fox jumps over the lazy dog
The quick brown fox jumps over the lazy dog
The quick brown fox jumps over the lazy dog
The quick brown fox jumps over the lazy dog
The quick brown fox jumps over the lazy dog
The quick brown fox jumps over the lazy dog
The quick brown fox
jumps over the lazy dog
The quick brown fox jumps over the lazy dog
The quick brown fox jumps over the lazy dog
The quick brown fox jumps over the lazy dog

illustration description

Bulk operations

Run one command, affect all your articles at once.

A shared footer file (e.g. "Further reading" links) kept in sync across all articles. Update the footer file once, then push all β€” the CLI finds the # Further reading marker in each article and replaces everything below it with the shared footer content:

`bash
dev push --update-toc "*.md"
`

Smart file renaming

When an article title changes, the filename should follow:

`bash
dev rename "*.md"
`

`bash
🦊 GitLab CI: A Battle-Tested Mono-Repo CI/CD Architecture
GITLAB_mono-repo-architecture.md β†’ GITLAB_ci-battle-tested-mono-repo-ci-cd-architecture.md

πŸ” Every Developer Should Review Code β€” Not Just Seniors
MISC_every-developer-should-review-code.md β†’ MISC_every-developer-review-code-seniors.md
`

Strips emoji, filters 80+ English stop words (a, the, and, how…), keeps the first 5 significant words, preserves the date/category prefix.

Article badges generation

Generate visual badges for a GitHub profile README:

`bash
dev badges --jpg "*.md"
`

Each badge overlays the article's cover image with its title, publication date, view count, and reading time. Articles are auto-grouped by category (extracted from filename prefix) and sorted by date within each group.

The most viewed articles get golden stars ⭐ β€” popularity is measured relative to the 2nd most viewed article (to avoid one viral post skewing everything). β‰₯90% of that reference = 3 stars, β‰₯50% = 2, β‰₯25% = 1. Stars and stats refresh on every run.

Produces a _ARTICLES.md file with badge images linking to each article. Here's my GitLab section:

🦊 GitLab CI: Achieving 3-Second Jobs on Million-Line Codebases 🦊 GitLab Runners: Which Topology for Fastest Job Execution?
πŸ”€ Efficient Git Workflow for Web Apps: Advancing Progressively from Scratch to Thriving πŸ”€πŸ¦Š GitLab: Forget GitKraken, Here are the Only Git Commands You Need
🦊 GitLab: A Python Script Displaying Latest Pipelines in a Group's Projects 🦊 GitLab: A Python Script Calculating DORA Metrics
🦊 GitLab CI: Deploy a Majestic Single Server Runner on AWS 🦊 GitLab CI: The Majestic Single Server Runner
🦊 GitLab CI YAML Modifications: Tackling the Feedback Loop Problem 🦊 GitLab CI Optimization: 15+ Tips for Faster Pipelines
🦊 GitLab CI: 10+ Best Practices to Avoid Widespread Anti-Patterns 🦊 GitLab Pages per Branch: The No-Compromise Hack to Serve Preview Pages
🦊 GitLab CI Jobs Attributes Sorter: A Python Script for Consistent YAML Files 🦊 GitLab Runners Topologies: Pros and Cons

Embed the file in a pinned article and all your articles become browsable from one place. Badges stay up to date with every dev badges run.

Broken link checking

Before publishing:

`bash
dev checklinks my-article.md
`

Catches dead URLs before readers do. Smart enough to treat HTTP 403/429 as "probably fine" (bot blocking, not a dead link). Also validates cover image and canonical URL from front matter. Works on all articles at once with dev checklinks "*.md".

Environment

Configure once, forget about it.

Organization publishing

One line in .env:

`bash
DEVTO_ORG=zenika
`

The CLI adds organization: zenika to the front matter and resolves the org ID automatically on push.

Proxy support for corporate environments

`bash
export HTTPS_PROXY=http://proxy.company.com:8080
dev push
`

All API calls, Kroki requests, and link checks go through the proxy. Self-signed certificates handled too.

Code

github.com/bcouetil/devto-cli

How I Built It

This is a TypeScript / Node.js CLI, forked from sinedied/devto-cli. Each feature was added incrementally β€” proxy support first, then Kroki diagrams, TOC generation, organization publishing, footer management, link checking, file renaming, ANSI blocks, badge generation, GitLab CI pipeline diagrams, and finally chart rendering.

This fork started as a one-line proxy fix and kept growing from there. Every feature was added because I needed it, not because it looked good on a feature list.

illustration description

Illustrations generated locally by Draw Things using Flux.1 [Schnell] model

Further reading


This article was enhanced with the assistance of an AI language model to ensure clarity and accuracy in the content, as English is not my native language.

Top comments (0)

Some comments may only be visible to logged-in visitors. Sign in to view all comments.