> ## Documentation Index
> Fetch the complete documentation index at: https://docs.mentioned.to/llms.txt
> Use this file to discover all available pages before exploring further.

# Blog to Subreddit Sync

> Configure and verify automatic full-content blog syncing into Reddit

Blog to subreddit sync copies full blog posts into Reddit-ready workspace posts and can queue them for Reddit publishing. The sync is configured per workspace and does not require per-company environment variables.

Use this workflow when a customer provides:

* A blog URL, RSS feed, sitemap, or blog index URL
* A destination subreddit
* An approved Reddit persona with a working browser session

## Configuration Model

Each sync config belongs to a workspace and stores:

| Field                 | Purpose                                                                            |
| --------------------- | ---------------------------------------------------------------------------------- |
| `blog_url`            | Blog index, feed, sitemap, or landing page to crawl                                |
| `subreddit`           | Destination subreddit, with or without `r/`                                        |
| `persona_id`          | Optional preferred persona; otherwise an active auth-completed persona is selected |
| `include_media`       | Extract inline images and render them into Reddit richtext                         |
| `active`              | Allows daily cron runs and publishing eligibility                                  |
| `publish_immediately` | Queues synced posts for publishing when the config is active                       |

For Cube, the verified config is:

```text theme={null}
workspace: cube-dev
config_id: 1
blog_url: https://cube.dev/blog
subreddit: r/cubedev
```

Cube can be verified in non-public mode before launch, or in live mode after posts have already been published.

## API-First Flow

Create or update a config:

```bash theme={null}
POST /api/v1/actions/blog-subreddit-syncs
```

Run a non-mutating preview:

```bash theme={null}
POST /api/v1/actions/blog-subreddit-syncs/:id/run
{
  "dry_run": true,
  "max_posts": 3
}
```

Run a real sync that writes drafts but does not publish:

```bash theme={null}
POST /api/v1/actions/blog-subreddit-syncs/:id/run
{
  "publish": false,
  "max_posts": 3
}
```

Check Reddit readiness without public posting:

```bash theme={null}
POST /api/v1/actions/blog-subreddit-syncs/:id/readiness
{
  "max_posts": 1,
  "persona_id": 238,
  "verify_media_upload": false
}
```

`persona_id` is optional. Use it to verify a specific workspace account without changing the sync config.
If the requested persona is not active, auth-completed, and browser-ready, the API fails instead of falling back.

`verify_media_upload=true` uploads Reddit media assets during preflight. Use it only when a human explicitly asks to verify media uploads.

## MCP Flow

MCP clients should use the same API actions in this order:

1. `get_blog_subreddit_syncs`
2. `post_blog_subreddit_syncs_id_run` with `dry_run=true`
3. `post_blog_subreddit_syncs_id_readiness`
4. `post_blog_subreddit_syncs_id_publish_preflight` only for a selected synced post

Do not run browser-backed checks concurrently. GoLogin can perform only one cloud browser operation at a time for a workspace API key.

## One-Command Cube Acceptance

Run the non-public Cube acceptance verifier:

```bash theme={null}
npm run verify:blog-subreddit-sync:cube -- \
  --workspace cube-dev \
  --config-id 1 \
  --blog-url https://cube.dev/blog \
  --subreddit cubedev \
  --max-posts 1 \
  --persona-id 238
```

The verifier checks:

* TypeScript
* Full-content dry-run discovery
* Media extraction
* Mid-sync config-change abort behavior
* Production HTTP API behavior with temporary read/write keys
* Reddit readiness through one GoLogin-backed browser session
* Banned persona exclusion
* Final database cleanup state

The default command does not submit a Reddit post and does not upload Reddit media assets.
`--persona-id` is optional; when provided, the verifier uses that workspace persona for browser-backed
readiness through the API and fails if the account is not active, auth-completed, and browser-ready.
Use `--allow-published` when verifying a config that has already completed live publishing.

## GoLogin Limit

GoLogin is serialized per workspace API key. The Cube verifier therefore uses one GoLogin-backed readiness check by default.

Do not run these at the same time for the same workspace:

* Blog sync readiness
* Blog sync publish preflight
* Persona OAuth preflight
* Any other Reddit browser automation using the same GoLogin API key

To also run the separate non-public live publish preflight, use:

```bash theme={null}
npm run verify:blog-subreddit-sync:cube -- --include-live-preflight
```

Only run that when no other GoLogin-backed job is active.

## Public Publish Gate

Public Reddit submission requires explicit human approval.

The live publish verifier will not publish unless called with:

```bash theme={null}
npm run verify:blog-subreddit-sync:live -- \
  --workspace cube-dev \
  --config-id 1 \
  --persona-id 238 \
  --confirm-live-reddit-post
```

Before using that flag, confirm:

* The selected synced post is approved
* The destination subreddit is correct
* The persona is approved for the customer
* The config is active and `publish_immediately=true`
* No other GoLogin-backed job is running for the same workspace

## Destination Changes During Sync

The sync fingerprints the config before each run. If the blog URL, subreddit, persona, active state, media setting, publish mode, or max-post setting changes while a run is active, the run aborts before writing or queueing more posts.

Queued publish tasks also carry the config fingerprint. If the destination changes before publishing, the task is skipped and the synced item returns to draft state.

## Expected Cube Acceptance State

After a live acceptance run with `--allow-published`, Cube should have no queued or failed sync items and should retain media-bearing published items. Before live publishing, a non-public acceptance run should leave `published posts: 0`.

```text theme={null}
temp API keys: 0
queued posts: 0
failed sync items: 0
media-bearing items: 3
config last_error: null
```
