← Back Contact →

A MAD GOAT Production

Content Ranch

Built before the hype.

Got Domains?

Content Ranch is a custom workflow built for publishing at scale. It turns feeds into evergreen content without depending on a traditional CMS, plugin stack, or manual publishing routine.

The workflow analyzes source material, constructs a durable angle, turns it into structured output, and publishes without a blogging platform.

content-ranch-skill/

The skill is the logic - the prompts, structure, and output rules that turn a feed into a finished article. It's packaged to run anywhere: n8n, Claude Code, a standalone server, Manus, or whatever runtime fits your stack.

Content Ranch itself is a workflow built and run in production. The skill is the portable piece at the center of it.

What the skill handles

  • Feed analysis and source item selection
  • Evergreen topic extraction from time-sensitive inputs
  • Article, metadata, and image prompt generation
  • Template-driven HTML output
  • Structured handoff to any publish target

What the workflow adds

  • The runtime - scheduling, triggers, orchestration
  • Integration with publish targets (FTP, API, CMS)
  • Environment-specific config and credentials
  • One implementation pattern among many possible builds

Example flow: A feed item enters the workflow, the system identifies a durable angle, generates an evergreen article and metadata, formats the output, and sends the finished content to the selected destination.

Why it matters: This is not here as a product pitch. It is here to show how MAD GOAT approaches workflow design, prompt structure, orchestration, and delivery.

SKILL.md 242 lines
# Feed to Evergreen Publisher

## Purpose

Turn feed items into original evergreen articles, then return or publish the result using a generic destination chosen by the user.

The feed is idea input only. It is used to surface a durable topic, not to create a near-rewrite of the source item.

This skill must stay generic. Do not introduce niche-specific assumptions, private site details, or hardcoded credentials.

## Core principles

1. Default to safe behavior.
2. Prefer evergreen content over short-lived news.
3. Treat the feed item as inspiration, not a content template.
4. Work in stateless environments.
5. Use saved site profiles only when local storage is actually available.
6. Keep one unified publish target schema.
7. Use one image concept with multiple output sizes unless the user explicitly asks for separate image concepts.
8. Never force a weak or duplicate article when no fresh candidate exists unless the profile explicitly allows fallback.

## Accepted entry modes

### A) Guided mode
Show a menu of saved sites when available. Also always offer:

```text
0. Add a new site
```

### B) Direct config mode
If the first user message begins with `CONFIG:`, parse the JSON object that follows and run the workflow immediately without showing the menu.

Allowed parsing behavior:
- allow whitespace before `CONFIG:`
- allow the JSON body either inline or inside one fenced JSON block
- reject invalid JSON with a clear validation message
- ignore unknown keys only if they are nested under a documented extension object such as `x_extra`
- otherwise surface unknown top-level keys as validation warnings

## Saved-site behavior

If writable local storage is available, site profiles may be stored under `sites/{slug}.json`.

If local storage is unavailable, do not pretend that profiles were saved. Continue in stateless mode only.

## Unified site profile

Every site profile must use this top-level structure:

```json
{
  "_site_name": "Example Site",
  "_site_slug": "example-site",
  "_site_topic": "What the site covers",
  "language": "en",
  "audience": "general readers",
  "dry_run": true,
  "feed_source": {},
  "editorial_rules": {},
  "internal_link_pool": [],
  "writing_profile": {},
  "meta_profile": {},
  "template": {},
  "seo_profile": {},
  "image_profile": {},
  "content_log": {},
  "publish_target": {
    "type": "show_in_chat",
    "mode": "draft",
    "settings": {}
  }
}
```

## Allowed publish target types

Use only these values for `publish_target.type`:

- `show_in_chat`
- `download_only`
- `webhook`
- `ftp`
- `sftp`
- `s3`
- `rest_api`
- `email`
- `notion`
- `google_docs`
- `wordpress`

Do not use vague catch-all values such as `cms` or ad hoc labels such as `show here`.

## Run flow

### Step 1 — Acquire site profile

Use one of these sources, in order:

1. `CONFIG:` payload passed in directly
2. saved site chosen by the user, if local storage exists
3. a new profile collected through onboarding

Validate the profile before continuing. If a required section is missing, stop and explain what is missing.

### Step 2 — Load the feed

Read the feed defined by `feed_source`.

If the feed cannot be read, explain the failure clearly and stop.

### Step 3 — Select a candidate item

Prefer items that can inspire evergreen educational or explanatory content.

Avoid or strongly deprioritize:

- breaking news
- earnings reports
- press releases
- event announcements
- dated roundups
- content that depends on current time references

If no good candidate exists, say so plainly instead of forcing a weak article.

Honor these fields when present:
- `editorial_rules.selection_mode`
- `editorial_rules.topic_schedule`
- `editorial_rules.selection_preferences`
- `editorial_rules.source_usage_mode`
- `editorial_rules.allow_weak_fallback`
- `content_log.history`

### Step 4 — Draft the article

Write a new original article inspired by the chosen item and aligned with the site profile.

Requirements:

- extract the durable underlying topic, not the original framing
- do not mirror the source title too closely
- do not paraphrase or summarize the source item section by section
- do not mention or cite the feed item in the final published body unless the user explicitly asks for attribution
- remove time-sensitive phrasing unless the user explicitly wants timely content
- do not quote long stretches from the source
- produce clean output in the requested `writing_profile.format`

### Step 5 — Refine for search and answer engines

If `seo_profile.enabled` is true:

- align with the primary keyword where natural
- add supporting entities and subtopics where helpful
- improve answerability for AI overviews and similar systems
- do not keyword-stuff
- do not invent statistics, percentages, or pseudo-citations

### Step 6 — Generate metadata

Create:

- title
- meta description
- slug
- keyword list when requested

Honor the limits in `meta_profile`.

### Step 7 — Generate image prompts when enabled

If `image_profile.enabled` is true:

- create one master image concept for the article by default
- adapt that same concept into each required output format
- keep subject, mood, and setting consistent across outputs
- return per-output alt text and crop notes
- only create separate image concepts if `image_profile.source_mode` explicitly requests them

If the environment cannot generate or upload images automatically, return prompts only.

### Step 8 — Prepare final payload

Assemble the final output package.

Minimum fields:

- article title
- article slug
- main body
- meta description
- selected source item
- publish target

The selected source item belongs in run metadata, not in the public-facing article body.

### Step 9 — Publish or return

Honor `dry_run` first.

- If `dry_run` is true, do not perform live publishing actions. Return the prepared output and clearly mark it as a dry run.
- If `dry_run` is false, publish using `publish_target`.
- If the runtime cannot perform the requested publish action, return the prepared payload with a clear explanation of what remains to be done.

For `download_only`, return a bundle shaped as described in `DELIVERY_BUNDLES.md`.

## Dedupe behavior

Use `content_log.history` when available. This is the preferred source of previously used topics, titles, slugs, dates, and source URLs.

If `content_log.history` is unavailable, use `editorial_rules.dedupe_titles_against` as a weaker fallback list of previously used or blocked titles.

Do not claim to enforce daily publish limits unless the profile contains real date-tracked history.

When selecting a new item, prefer a materially different article angle if a similar title or topic has already been used recently.

## Onboarding rules

Use `prompt.onboarding.txt` for guided setup.

During onboarding, explain choices in plain language. Avoid technical jargon unless the user asks for it.

Map the user's publishing choice to one of the allowed `publish_target.type` values.

## Template behavior

If `template.enabled` is true, render HTML only after the final markdown and metadata are complete.

Use `template/page.html` together with `TEMPLATE_VARIABLES.md`.
Do not assume a templating engine other than simple Handlebars-style conditionals documented in that file.

## Non-goals

Do not:

- expose secrets
- claim integrations that are not actually available
- assume local file persistence exists
- hardcode a vertical, market, brand, or feed source
- silently switch a draft workflow to live publishing
- present source-trace citations as part of the finished article unless requested