$ show increments/qiita-cli
Qiita CLI is a command-line tool and preview server for managing Qiita blog posts locally. It allows users to create, edit, preview (with hot-reload), and publish articles and slides (Marp-based) to the Qiita platform via its REST API. The architecture separates CLI commands (init, login, new, preview, publish, pull) from a file-system-backed repository layer that synchronizes local markdown files with Qiita's remote state using a `.remote` mirror directory. A React-based web frontend provides a sidebar for navigating articles/slides and an embedded preview of rendered Markdown (including MathJax and embedded scripts). The server also supports Marp slide preview with shadow DOM isolation for CSS scoping. The codebase is well-structured, uses TypeScript, has comprehensive unit tests, and follows modern Node.js patterns (async/await, error handling, dependency injection). It is actively maintained by Qiita Inc. and targets Node.js 22+.
The LLM identified 5 files worth highlighting for reuse:
Singleton Config class that manages credential directories, user config (qiita.config.json), root directories, and cache directories with XDG support and environment variable overrides. Includes a Credential class that reads/writes a JSON file with profile-based token management, supporting `QIITA_TOKEN` env var fallback and `0o600` file permissions. Reusable for any CLI tool needing secure config and credential storage.
FileSystemRepo class that manages a local directory of markdown articles, using a hidden `.remote` subdirectory as a mirror of the last known state from the API. Provides load/create/save/publish operations with diff detection against the mirror (via FileContent.equals()), staleness checks, and automatic UUID injection after publishing. The pattern of maintaining a local mirror to detect modifications and prevent overwriting remote changes is a clean, extractable design for any local-remote content sync system.
Two-stage validation for publishing: first checks frontmatter types (via checkFrontmatterType), then validates business rules (title, body, tags, organization+privacy conflicts, campaign agreements), and finally warns if the local file is older than the remote. The layered approach ensures type errors are reported before value errors, making debugging easier. The Validator interface (getMessage, isValid) is a reusable composable pattern for any multi-field validation.
Minimal file-based cache for storing the latest npm package version with a 12-hour TTL. Uses JSON serialization and respects XDG cache directory. Could be extracted and reused by any CLI tool that needs to check for updates without hitting the registry on every invocation.
Renders Marp-generated slide HTML inside a Shadow DOM to prevent app styles from leaking into or being overridden by the slide content. Uses React portal to inject the style tag and slide HTML into the shadow root. This is a non-obvious solution to a common problem when embedding third-party HTML with global CSS (like Marp) into a React application.