diff --git a/Gemfile b/Gemfile index 56e0f1b4..0e904547 100644 --- a/Gemfile +++ b/Gemfile @@ -2,5 +2,5 @@ source 'https://rubygems.org' -gem 'html2rss', git: 'https://github.com/html2rss/html2rss.git' +gem 'html2rss', '~> 0.26' gem 'html2rss-configs', git: 'https://github.com/html2rss/html2rss-configs.git' diff --git a/Gemfile.lock b/Gemfile.lock index e89e020a..4b93f2f9 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,36 +1,10 @@ GIT remote: https://github.com/html2rss/html2rss-configs.git - revision: d9e3dc55b38514eb9cd4a17cb0285d9ef73bc9d5 + revision: ebda084dfdb87627091f0336208553204d073c7b specs: html2rss-configs (0.2.0) html2rss -GIT - remote: https://github.com/html2rss/html2rss.git - revision: aa974733c6e88a5c934f445516d9752dfa316067 - specs: - html2rss (0.25.0) - addressable (~> 2.7) - brotli - dry-validation - faraday (> 2.0.1, < 3.0) - faraday-follow_redirects - faraday-gzip (~> 3) - kramdown - mcp (~> 1.0) - mime-types (> 3.0) - nokogiri (>= 1.10, < 2.0) - rack (~> 3.0) - rackup (~> 2.0) - regexp_parser - reverse_markdown (~> 3.0) - rss - sanitize - thor - tzinfo - webrick (~> 1.9) - zeitwerk - GEM remote: https://rubygems.org/ specs: @@ -87,6 +61,27 @@ GEM faraday-net_http (3.4.4) net-http (~> 0.5) hana (1.3.7) + html2rss (0.26.0) + addressable (~> 2.7) + brotli + dry-validation + faraday (> 2.0.1, < 3.0) + faraday-follow_redirects + faraday-gzip (~> 3) + kramdown + mcp (~> 1.0) + mime-types (> 3.0) + nokogiri (>= 1.10, < 2.0) + rack (~> 3.0) + rackup (~> 2.0) + regexp_parser + reverse_markdown (~> 3.0) + rss + sanitize + thor + tzinfo + webrick (~> 1.9) + zeitwerk json (2.21.2) json_schemer (2.5.0) bigdecimal @@ -138,7 +133,7 @@ PLATFORMS x86_64-linux DEPENDENCIES - html2rss! + html2rss (~> 0.26) html2rss-configs! BUNDLED WITH diff --git a/astro.config.mjs b/astro.config.mjs index 10284381..81b8a06d 100644 --- a/astro.config.mjs +++ b/astro.config.mjs @@ -14,7 +14,7 @@ export default defineConfig({ "/components/html2rss-configs": "/creating-custom-feeds/", "/components": "/", "/web-application/how-to/deployment": "/web-application/deployment/", - "/web-application/how-to/automatic-updates": "/web-application/deployment/#auto-update-with-watchtower", + "/web-application/how-to/automatic-updates": "/web-application/deployment/", "/web-application/how-to/use-automatic-feed-generation": "/web-application/guides/use-the-feed-directory/", "/web-application/how-to": "/web-application/guides/", diff --git a/src/components/docs/DockerComposeSnippet.astro b/src/components/docs/DockerComposeSnippet.astro index ee161f5c..f8b58ebd 100644 --- a/src/components/docs/DockerComposeSnippet.astro +++ b/src/components/docs/DockerComposeSnippet.astro @@ -1,9 +1,9 @@ --- import { Code } from "@astrojs/starlight/components"; -import { botasaurusImage, caddyImage, watchtowerImage, webImage } from "../../data/docker"; +import { botasaurusImage, caddyImage, webImage } from "../../data/docker"; interface Props { - variant: "minimal" | "productionCaddy" | "secure" | "watchtower" | "resourceGuardrails"; + variant: "minimal" | "productionCaddy" | "secure" | "resourceGuardrails"; } const { variant } = Astro.props; @@ -78,15 +78,6 @@ volumes: botasaurus: image: ${botasaurusImage} restart: unless-stopped`, - watchtower: `services: - watchtower: - image: ${watchtowerImage} - restart: unless-stopped - volumes: - - /var/run/docker.sock:/var/run/docker.sock:ro - # Optional for private registries only: - # - "\${HOME}/.docker/config.json:/config.json:ro" - command: --cleanup --interval 7200 html2rss-web botasaurus caddy`, resourceGuardrails: `services: html2rss-web: image: ${webImage} diff --git a/src/content/docs/creating-custom-feeds.mdx b/src/content/docs/creating-custom-feeds.mdx index 22422ece..f2dd76d2 100644 --- a/src/content/docs/creating-custom-feeds.mdx +++ b/src/content/docs/creating-custom-feeds.mdx @@ -31,11 +31,12 @@ When existing feeds or auto-sourcing are not enough, write a YAML config for the ## Recommended Workflow 1. **Inspect the live page** in your browser developer tools -2. **Write the smallest useful config** that extracts items, titles, and links -3. **Validate the config** with `html2rss validate your-config.yml` -4. **Render the feed** with `html2rss feed your-config.yml` -5. **Add it to `html2rss-web`** so you can use it through your normal instance -6. **Escalate request strategy when needed**: use a browser-based rendering strategy only when troubleshooting requires it +2. **Optionally draft with capture** — `html2rss capture https://example.com/articles > your-config.yml` (see [Capturing Feed Configs](/ruby-gem/guides/capturing-feed-configs/)) +3. **Write or refine the smallest useful config** that extracts items, titles, and links +4. **Validate the config** with `html2rss validate your-config.yml` +5. **Render the feed** with `html2rss feed your-config.yml` +6. **Add it to `html2rss-web`** so you can use it through your normal instance +7. **Escalate request strategy when needed**: use Botasaurus (`strategy: botasaurus` or `auto` with `BOTASAURUS_SCRAPER_URL`) only when troubleshooting requires browser rendering This order keeps iteration fast and makes it easier to see whether the problem is the page structure, your selectors, or the fetch strategy. @@ -188,8 +189,34 @@ there. **Help the community by sharing your config:** 1. Go to [html2rss-configs on GitHub](https://github.com/html2rss/html2rss-configs) -2. Click "Fork" → "Add file" → Create `domain.com.yml` -3. Paste your config → "Commit new file" → "Open pull request" +2. Click "Fork" → "Add file" → Create `domain.com/name.yml` under `lib/html2rss/configs/` +3. Include top-level `directory.topics` (required for Feed Directory configs) using the controlled vocabulary below +4. Paste your config → "Commit new file" → "Open pull request" + +Example catalog metadata: + + + +Allowed `directory.topics` values (prefer 1–2 primary topics): `sports`, `energy`, `tech`, `science`, `news`, `entertainment`, `jobs`, `finance`, `security`, `travel`, `environment`, `consumer`, `civic`, `product`, `research`. **Need help?** See our [contribution guide](/get-involved/contributing/) for detailed instructions. diff --git a/src/content/docs/feed-directory/index.mdx b/src/content/docs/feed-directory/index.mdx index 1efdcb18..ffbe6045 100644 --- a/src/content/docs/feed-directory/index.mdx +++ b/src/content/docs/feed-directory/index.mdx @@ -14,7 +14,7 @@ import FeedDirectory from "../../../components/FeedDirectory.astro"; --- -Need the main onboarding path first? Start with [Getting Started](/web-application/getting-started/) and create a feed from your own page URL. The directory below is the packaged fallback/catalog path for fast demos, known sample sources, or cases where the catalog already covers your site. +Need the main onboarding path first? Start with [Getting Started](/web-application/getting-started/) and create a feed from your own page URL. The directory below is the packaged fallback path for fast demos, known sample sources, or cases where a curated config already covers your site. Use the topic and language filters to narrow the list; export OPML when you want to subscribe to several feeds at once. Need a different instance? You can use the built-in default, self-host your own, or find more options on the [community-run wiki](https://github.com/html2rss/html2rss-web/wiki/Instances). diff --git a/src/content/docs/get-involved/contributing.mdx b/src/content/docs/get-involved/contributing.mdx index 1dbeca90..b764dbf2 100644 --- a/src/content/docs/get-involved/contributing.mdx +++ b/src/content/docs/get-involved/contributing.mdx @@ -26,10 +26,12 @@ Are you missing an RSS feed for a website? You can create your own feed config a **The easiest way to contribute:** 1. Go to [html2rss-configs on GitHub](https://github.com/html2rss/html2rss-configs) -2. Click "Fork" → "Add file" → Create `domain.com.yml` -3. Paste your config → "Commit new file" → "Open pull request" +2. Click "Fork" → "Add file" → Create `domain.com/name.yml` under `lib/html2rss/configs/` +3. Include top-level `directory.topics` (non-empty) from the controlled vocabulary (`tech`, `news`, `security`, `research`, … — see [Creating Custom Feeds](/creating-custom-feeds/#sharing-your-config)) +4. Prefer setting `channel.language` when the page language is clear +5. Paste your config → "Commit new file" → "Open pull request" -**Need help writing configs?** See our [Creating Custom Feeds](/creating-custom-feeds/) guide. +**Need help writing configs?** Start from [Capturing Feed Configs](/ruby-gem/guides/capturing-feed-configs/) or the [Creating Custom Feeds](/creating-custom-feeds/) guide. **Want to test your config first?** Use the [Ruby gem](/ruby-gem/installation/) to test it locally: diff --git a/src/content/docs/ruby-gem/guides/ai-agent-workflows.mdx b/src/content/docs/ruby-gem/guides/ai-agent-workflows.mdx new file mode 100644 index 00000000..df090b5b --- /dev/null +++ b/src/content/docs/ruby-gem/guides/ai-agent-workflows.mdx @@ -0,0 +1,103 @@ +--- +title: AI Agent Workflows with MCP +description: Guide to integrating html2rss with AI agents, Claude Desktop, and Cursor using the Model Context Protocol (MCP). +--- + +import { Code } from "@astrojs/starlight/components"; + +`html2rss` includes a native [Model Context Protocol (MCP)](https://modelcontextprotocol.io/) server. This allows AI assistants in tools like Cursor, Claude Desktop, and GitHub Copilot to scrape pages, capture feed configurations, and generate RSS feeds autonomously. + +## Why Use MCP? + +Without MCP, agents must invoke shell commands, manage output buffers, and parse unstructured text. With MCP: + +- The agent automatically discovers available tools, arguments, and return types. +- Responses are structured (JSON Feed objects, configuration schemas, and RSS XML). +- Agents can inspect, capture, validate, and verify feeds iteratively in a closed feedback loop. + +## Client Setup + +### 1. Version Manager Shims (mise, asdf, rbenv, chruby) + +Because version managers manage Ruby runtimes and gem paths through environment shims, configure your MCP client to invoke the version manager executable rather than a bare `html2rss` command. + + + +### 2. Cursor Configuration + +Add `html2rss` to your Cursor MCP settings (`~/.cursor/mcp.json` or `.cursor/mcp.json`): + + + +_(If using `asdf`, replace `"command": "mise"` with `"asdf"` and `"args": ["exec", "html2rss", "mcp"]`.)_ + +### 3. Claude Desktop Configuration + +Add `html2rss` to your Claude Desktop configuration (`~/Library/Application Support/Claude/claude_desktop_config.json` on macOS or `%APPDATA%\\Claude\\claude_desktop_config.json` on Windows): + + + +## Autonomous Workflow Patterns + +### Pattern A: One-Shot Content Scraping + +When an agent needs articles immediately without saving a feed configuration: + +1. The agent calls `scrape_url` with the target URL. +2. `html2rss` runs auto-source extraction (Schema.org, JSON state, semantic HTML) and returns a JSON Feed items array. +3. If the page is protected or rendered with JavaScript, the agent calls `inspect_url` to diagnose the structure, then retries `scrape_url` with `strategy: "botasaurus"`. + +### Pattern B: Iterative Feed Config Authoring + +When an agent is tasked with creating a durable YAML feed configuration: + +1. **Inspect:** The agent calls `inspect_url` to check content type, SST node counts, and eligible scrapers. +2. **Capture:** The agent runs `capture_config` to derive CSS selectors for items, title, link, and description. +3. **Refine:** The agent reviews the derived selectors or asks the human user for domain-specific adjustments. +4. **Validate:** The agent passes the configuration to `validate_config` to verify schema conformance. +5. **Apply:** The agent tests the final configuration with `apply_config` to produce and inspect live RSS XML. + +## JavaScript-Rendered Sites (Botasaurus) + +For dynamic JavaScript single-page applications or sites protected by anti-bot measures, launch the Botasaurus scrape service: + + + +Ensure `BOTASAURUS_SCRAPER_URL` is accessible (typically `http://127.0.0.1:4010`) in the environment where the MCP server runs. Agents can then pass `strategy: "botasaurus"` to `scrape_url`, `inspect_url`, and `capture_config`. diff --git a/src/content/docs/ruby-gem/guides/backward-compatibility.mdx b/src/content/docs/ruby-gem/guides/backward-compatibility.mdx index 9357cf48..39ebd2b4 100644 --- a/src/content/docs/ruby-gem/guides/backward-compatibility.mdx +++ b/src/content/docs/ruby-gem/guides/backward-compatibility.mdx @@ -7,6 +7,13 @@ import { Code } from "@astrojs/starlight/components"; This page outlines recent breaking changes, purged legacy aliases, and migration steps for older feed configurations. +## 0.26.0 + +Upgrade notes for configs and integrators targeting gem **0.26.0**: + +1. **Browserless strategy removal** — The `browserless` strategy, `puppeteer-ruby` dependency, interaction budgets, and `request.browserless.*` options have been completely removed. +2. **Botasaurus as browser transport** — Browser-based scraping and anti-bot bypassing now run through `botasaurus` (`BOTASAURUS_SCRAPER_URL`). Use `strategy: auto` (which tries `faraday` -> `botasaurus`) or pin `strategy: botasaurus` directly. + ## 0.25.0 Upgrade notes for configs and integrators targeting gem **0.25.0**: @@ -67,11 +74,11 @@ Update any occurrences of `link`, `pubDate`, or `updated` in your `selectors` bl # Deprecated / Removed channel: url: "https://example.com/articles" - strategy: browserless + strategy: botasaurus headers: User-Agent: "CustomAgent/1.0" # Current & Required - strategy: browserless + strategy: botasaurus headers: User-Agent: "CustomAgent/1.0" channel: @@ -84,10 +91,10 @@ Update any occurrences of `link`, `pubDate`, or `updated` in your `selectors` bl When upgrading to modern `html2rss` releases: -1. **Rename URL selectors**: Ensure article URL selectors use `url` rather than `link`. -2. **Rename date selectors**: Ensure date selectors use `published_at` rather than `updated` or `pubDate`. -3. **Move channel-level transport keys**: Ensure `strategy` and `headers` are defined at the top level of the YAML file. -4. **Pin Browserless when needed**: If you relied on `auto` falling through to Browserless, set `strategy: browserless` (or `--strategy browserless`). +1. **Migrate Browserless to Botasaurus**: Update any feeds using `strategy: browserless` or `request.browserless` to `strategy: botasaurus` or `strategy: auto` with `BOTASAURUS_SCRAPER_URL`. +2. **Rename URL selectors**: Ensure article URL selectors use `url` rather than `link`. +3. **Rename date selectors**: Ensure date selectors use `published_at` rather than `updated` or `pubDate`. +4. **Move channel-level transport keys**: Ensure `strategy` and `headers` are defined at the top level of the YAML file. 5. **Use `enclosure` for RSS media**: Do not rely on `image` becoming an RSS ``; select podcast/media URLs with `enclosure`. 6. **Prefer `feed_result` for dual-format / cache**: Integrators that need RSS + JSON Feed from one scrape (or Marshal caching) should use `Html2rss.feed_result` and `status.to_h`. 7. **Validate configurations**: Run `html2rss validate config.yml` to ensure your YAML conforms to the current schema. diff --git a/src/content/docs/ruby-gem/guides/capturing-feed-configs.mdx b/src/content/docs/ruby-gem/guides/capturing-feed-configs.mdx new file mode 100644 index 00000000..9b8bb7ce --- /dev/null +++ b/src/content/docs/ruby-gem/guides/capturing-feed-configs.mdx @@ -0,0 +1,116 @@ +--- +title: Capturing Feed Configs +description: Derive a reusable YAML feed config from a URL with html2rss capture, then validate and refine selectors. +--- + +import { Aside, Code } from "@astrojs/starlight/components"; + +`html2rss capture` analyzes a page through the auto-source pipeline and prints a reusable feed config with derived CSS selectors. Use it when you want a first draft faster than hand-writing selectors from scratch. + + + +## When to Capture + +Use capture when: + +- you are writing a new custom feed and want a starting YAML +- auto-source finds articles, but you want durable selectors for review +- an AI agent or MCP client should produce a config before `validate` / `apply` + +Prefer [automatic feed generation](/web-application/guides/use-automatic-feed-generation/) when you only need items now and do not need a saved config. + +## CLI + +Print YAML to stdout: + + my-feed.yml +`} + lang="bash" +/> + +Common options: + +- `--strategy` — `auto`, `faraday`, `botasaurus`, or `local_file` (default `auto`) +- `--items_selector` — CSS selector hint for item cards +- `--limit` — maximum articles kept while deriving selectors +- `--max-redirects` / `--max-requests` — request budget overrides +- `--input` — local HTML file (sets `local_file` strategy) + +See the [CLI reference](/ruby-gem/reference/cli-reference/#capture) for the full flag list. + +## Ruby API + + + +## How It Works + +1. **Request** — fetches the page with the chosen strategy +2. **Discover** — runs AutoSource to extract articles +3. **Analyze** — normalizes the page into an SST document and maps segment positions back to articles +4. **Derive** — builds CSS selectors from SST tag paths for items, title, link, and description +5. **Assemble** — returns a config hash ready for YAML or `Html2rss.feed` + +Capture segment discovery currently uses the list Segmenter strategy only (not AutoSource cluster/semantic heuristics). When the draft is weak, pass `--items_selector` or refine selectors by hand. + +## What Capture Derives + +Capture focuses on: + +- `channel.url` (and related channel defaults) +- `selectors.items` +- `selectors.title` +- `selectors.url` (derived href selector) +- `selectors.description` when a distinct description root exists + +It does not invent author, `published_at`, categories, or enclosure selectors. Add those manually when the page exposes them reliably. + +Description is omitted when it would resolve to the invalid CSS selector `.` (item root equals description root). + +## Recommended Follow-Up + +1. Validate: `html2rss validate my-feed.yml` +2. Render: `html2rss feed my-feed.yml` +3. Tighten selectors, strategy, or `request.botasaurus` options if needed +4. For Feed Directory contributions, add `directory.topics` (see [Creating Custom Feeds](/creating-custom-feeds/#sharing-your-config)) + +## Related + +- [CLI reference — Capture](/ruby-gem/reference/cli-reference/#capture) +- [AI agent workflows (MCP `capture_config`)](/ruby-gem/guides/ai-agent-workflows/) +- [Creating custom feeds](/creating-custom-feeds/) +- [Auto Source](/ruby-gem/reference/auto-source/) diff --git a/src/content/docs/ruby-gem/guides/custom-http-requests.mdx b/src/content/docs/ruby-gem/guides/custom-http-requests.mdx index 3c385a00..e9302d8b 100644 --- a/src/content/docs/ruby-gem/guides/custom-http-requests.mdx +++ b/src/content/docs/ruby-gem/guides/custom-http-requests.mdx @@ -73,8 +73,7 @@ Request budgets are configured under `request`, not as top-level keys: - `request.max_redirects` limits redirect hops - `request.max_requests` limits the total request budget for the feed build -- `request.browserless.*` is reserved for Browserless-only behavior such as preload actions -- `request.botasaurus.*` is reserved for Botasaurus-only behavior such as navigation mode and retries +- `request.botasaurus.*` is reserved for Botasaurus-only behavior such as navigation mode, retries, header/cookie forwarding, and scroll options ## Common Use Cases diff --git a/src/content/docs/ruby-gem/guides/handling-dynamic-content.mdx b/src/content/docs/ruby-gem/guides/handling-dynamic-content.mdx index fbe522f4..dd206831 100644 --- a/src/content/docs/ruby-gem/guides/handling-dynamic-content.mdx +++ b/src/content/docs/ruby-gem/guides/handling-dynamic-content.mdx @@ -1,6 +1,6 @@ --- title: Handling Dynamic Content -description: "Learn how to handle JavaScript-heavy websites and dynamic content with html2rss using browser-based extraction strategies." +description: "Learn how to handle JavaScript-heavy websites and dynamic content with html2rss using Botasaurus browser-based extraction strategies." --- import { Code } from "@astrojs/starlight/components"; @@ -9,26 +9,25 @@ Some websites load their content dynamically using JavaScript. Static fetch path ## Solution -Default `strategy: auto` already tries `faraday` then `botasaurus` (when `BOTASAURUS_SCRAPER_URL` is configured). That covers many JS-rendered listing pages without pinning a strategy. +Default `strategy: auto` automatically tries `faraday` first, then falls back to `botasaurus` when `BOTASAURUS_SCRAPER_URL` is configured. This handles many JS-rendered listing pages without needing custom configuration. -Pin [`browserless`](/ruby-gem/reference/strategy/#browserless) when you need headless Chrome with preload (wait, click, scroll) or other Browserless-only controls — Browserless is not part of the `auto` chain. - -Keep the strategy at the top level and put request-specific options under `request`: +When a site requires browser rendering or anti-bot bypass by default, you can explicitly set `strategy: botasaurus` and configure request controls under `request.botasaurus`: -## When to Use Browser-Based Extraction +## When to Use Botasaurus Extraction -A browser-based extraction strategy is necessary when: +Botasaurus extraction is ideal when: -- **Content loads after page load** - JavaScript fetches data from APIs +- **Content loads after page load** - JavaScript fetches data dynamically - **Single Page Applications (SPAs)** - React, Vue, Angular apps -- **Infinite scroll** - Content loads as you scroll -- **Dynamic forms** - Content changes based on user interaction +- **Anti-bot interstitials** - Cloudflare, Google search referrers, or challenge pages +- **Scroll-triggered content** - Infinite scroll lists (`scroll_to_bottom: true`) -## Preload Actions +## Botasaurus Request Controls -For dynamic sites, rendering once is often not enough. Use `request.browserless.preload` to wait, click, or scroll before the -HTML snapshot is taken. +Configure browser actions under `request.botasaurus`: -### Wait Before Capturing Dynamic Content +### Wait for Elements -### Click "Load More" Buttons +### Scroll for Infinite Content -### Scroll Infinite Lists +### Anti-Bot Bypass Navigation Modes -These preload steps can be combined in a single config when a site needs several interactions before all items appear. +### JSON Loaded Over XHR + +When Botasaurus uses the browser tier, captured JSON XHR/fetch bodies feed AutoSource `xhr_articles` automatically (enabled by default). Prefer `strategy: botasaurus` (or `auto` with `BOTASAURUS_SCRAPER_URL`) for SPA listing pages that hydrate article lists over the network rather than embedding them in HTML. See [Auto Source](/ruby-gem/reference/auto-source/) and [Strategy](/ruby-gem/reference/strategy/#botasaurus). ## Performance Considerations -Browser-based extraction is slower than default static HTTP fetching because it: +Browser-based extraction uses more resources than static HTTP fetching because it: -- Launches a headless Chrome browser -- Renders the full page with JavaScript -- Takes more memory and CPU resources +- Renders pages in an automated Chrome instance +- Executes JavaScript and handles DOM events +- Manages browser pools and network emulation -**Use static HTTP fetching for static content** and switch to browser-based extraction when needed. See the [Strategy Reference](/ruby-gem/reference/strategy/) for concrete transports, defaults, and environment requirements. +Use static HTTP fetching (`faraday`) for static content, and lean on `auto` or explicit `botasaurus` strategies when browser rendering is required. See the [Strategy Reference](/ruby-gem/reference/strategy/) for details. ## Related Topics - **[Strategy Reference](/ruby-gem/reference/strategy/)** - Complete strategy documentation - **[Troubleshooting](/troubleshooting/troubleshooting/)** - Common issues with dynamic content -- **[Advanced Features](/ruby-gem/guides/advanced-features/)** - Performance optimization tips diff --git a/src/content/docs/ruby-gem/index.mdx b/src/content/docs/ruby-gem/index.mdx index 4fe10115..91ce54fb 100644 --- a/src/content/docs/ruby-gem/index.mdx +++ b/src/content/docs/ruby-gem/index.mdx @@ -23,5 +23,5 @@ If you are getting started with `html2rss`, we recommend starting with the [**fi ## Documentation Sections - **[Tutorials](/ruby-gem/tutorials/your-first-feed/)**: Step-by-step guides to help you get started with `html2rss`. -- **[Guides](/ruby-gem/guides/)**: Practical examples and solutions for common tasks. -- **[Reference](/ruby-gem/reference/)**: Detailed information on configuration options. +- **[Guides](/ruby-gem/guides/)**: Practical examples and solutions for common tasks, including [capturing feed configs](/ruby-gem/guides/capturing-feed-configs/) and [AI agent workflows](/ruby-gem/guides/ai-agent-workflows/). +- **[Reference](/ruby-gem/reference/)**: Detailed information on configuration options, CLI commands, and the [MCP server](/ruby-gem/reference/mcp-server/). diff --git a/src/content/docs/ruby-gem/reference/auto-source.mdx b/src/content/docs/ruby-gem/reference/auto-source.mdx index 605804a3..ce9c9bc6 100644 --- a/src/content/docs/ruby-gem/reference/auto-source.mdx +++ b/src/content/docs/ruby-gem/reference/auto-source.mdx @@ -28,18 +28,20 @@ To enable it, add `auto_source: {}` to your configuration: 4. **`schema`:** Parses `