Skip to content

Latest commit

 

History

History
266 lines (204 loc) · 9.09 KB

File metadata and controls

266 lines (204 loc) · 9.09 KB

Ghost Publishing from Org-Mode

Overview

This library provides a complete workflow for publishing org-mode files to Ghost CMS with rich media support. The workflow separates concerns into distinct phases:

PhasePurposeSpeedInteractive
GenerateCreate media (TTS, images, video)FastYes, iterate
EnrichAdd metadata to media/embedsSlowerOnce
PreviewView HTML locallyFastYes
PublishSend to GhostFastOnce

Installation

(add-to-list 'load-path "/srv/research/org/ox-ghost")
(require 'ghost-publish)

;; Configure Ghost connection
(setq ghost-publish-url "https://www.ii.coop"
      ghost-publish-admin-key "YOUR_ADMIN_API_KEY")

Phase 1: Generation

Generation functions create media files, upload them to Ghost, and return basic org syntax. Run these iteratively while developing your post.

Text-to-Speech Audio

#+CALL: ghost-tts("Welcome to my tutorial")

Returns:

Welcome to my tutorial

Generated Images

#+CALL: ghost-image("Chapter One" "#e74c3c" "#c0392b")

Returns:

[[https://ghost.site/content/images/2026/01/img-xxx.png][Chapter One]]

Generated Video

#+CALL: ghost-video("Org Mode Powers This" "#2d3436")

Returns:

Org Mode Powers This

Direct Upload

#+CALL: ghost-upload("/path/to/file.png")

Returns the Ghost URL for the uploaded file.

Phase 2: Enrichment

Once content is stable, enrich adds metadata required by Ghost’s Lexical format. This is a separate step because:

  1. Enrichment involves HTTP requests (slower)
  2. You don’t want to re-fetch metadata on every iteration
  3. You can review enriched content before publishing

Commands

CommandDescription
M-x ghost-enrich-bufferEnrich all blocks in current buffer
M-x ghost-enrich-regionEnrich blocks in selected region
M-x ghost-enrich-at-pointEnrich single block at cursor

What Gets Enriched

Block TypeAdded Metadata
VIDEO:width, :height, :duration, :mimeType, :thumbnailSrc
AUDIO:duration, :mimeType
EMBED:html (iframe code for YouTube/Vimeo)
BOOKMARK:title, :description, :icon, :thumbnail

Before Enrichment

My video description

First YouTube video

After Enrichment (M-x ghost-enrich-buffer)

My video description

First YouTube video

Phase 3: Preview

Preview renders the org file to HTML without publishing, so you can verify appearance locally.

CommandDescription
M-x ghost-previewExport to HTML, open in browser
M-x ghost-preview-jsonExport to Lexical JSON, view in buffer

Phase 4: Publish

When satisfied with preview, publish to Ghost.

CommandDescription
M-x ghost-publishCreate new post (draft)
M-x ghost-updateUpdate existing post
M-x ghost-publish-and-openPublish and open in browser

Complete Workflow Example

1. Create org file with content
   #+TITLE: My Tutorial
   #+TAGS: tutorial, demo

   * Introduction
   #+CALL: ghost-tts("Welcome to my tutorial")

   * Main Content
   #+CALL: ghost-image("Step One" "#667eea" "#764ba2")
   ...

2. Iterate on generation
   - C-c C-c on blocks to regenerate
   - Preview inline results
   - Adjust text, colors, etc.

3. Enrich when satisfied
   M-x ghost-enrich-buffer
   - Review the added metadata
   - Verify blocks look correct

4. Preview locally
   M-x ghost-preview
   - Opens HTML in browser
   - Check layout, media playback

5. Publish
   M-x ghost-publish
   - Creates draft on Ghost
   - Returns URL for review

Style Guide for Org Files

Required Headers

#+TITLE: Post Title
#+DATE: 2026-01-29
#+AUTHOR: ii.coop
#+TAGS: tag1, tag2, tag3
#+EXCERPT: Brief description for previews and SEO.

Content Blocks

Use CaseRecommended Block
Important callout#+BEGIN_CALLOUT :emoji
Collapsible content#+BEGIN_TOGGLE
External video#+BEGIN_EMBED :url
Uploaded video#+BEGIN_VIDEO :src
Audio player#+BEGIN_AUDIO :src
Link preview#+BEGIN_BOOKMARK :url
Call to action#+BEGIN_BUTTON :url

Generated Media Guidelines

  • TTS: Keep text concise (under 20 words per block)
  • Images: Use contrasting gradient colors for readability
  • Video: Keep under 10 seconds for concept demos

Color Palette

Standard gradients for consistency:

PurposeStartEnd
Info#667eea#764ba2
Warning#f39c12#e74c3c
Success#00b894#00cec9
Dark#2d3436#636e72

Dependencies

External tools required:

ToolPurposeInstall
espeak-ngText-to-speechdnf install espeak-ng
ffmpegAudio/video processingdnf install ffmpeg
ffprobeMedia metadata(included with ffmpeg)
magickImage generationdnf install ImageMagick
curlHTTP requests(usually pre-installed)
nodeGhost API clientdnf install nodejs

Architecture

┌─────────────────────────────────────────────────────────┐
│                    Org File (.org)                      │
│  #+TITLE, content, #+CALL: ghost-* functions            │
└─────────────────────────────────────────────────────────┘
                           │
        ┌──────────────────┼──────────────────┐
        ▼                  ▼                  ▼
   ┌─────────┐       ┌──────────┐       ┌─────────┐
   │ Generate│       │  Enrich  │       │ Preview │
   │ (iterate)│       │  (once)  │       │ (local) │
   └─────────┘       └──────────┘       └─────────┘
        │                  │                  │
        ▼                  ▼                  ▼
   ┌─────────┐       ┌──────────┐       ┌─────────┐
   │espeak-ng│       │ ffprobe  │       │ Browser │
   │ ffmpeg  │       │  curl    │       │         │
   │ magick  │       │          │       │         │
   └─────────┘       └──────────┘       └─────────┘
        │                  │
        └────────┬─────────┘
                 ▼
        ┌─────────────────┐
        │   ghost.js      │
        │ (upload/publish)│
        └─────────────────┘
                 │
                 ▼
        ┌─────────────────┐
        │   Ghost CMS     │
        └─────────────────┘