diff --git a/about.md b/about.md
new file mode 100644
index 00000000..24ba6587
--- /dev/null
+++ b/about.md
@@ -0,0 +1,34 @@
+---
+layout: default
+title: About html2rss
+nav_order: 2
+---
+
+# About html2rss
+
+`html2rss` is an open-source project dedicated to empowering you to take control of your web content. In an age where traditional RSS feeds are often missing, `html2rss` provides a robust and flexible solution to convert almost any HTML content into a structured RSS format.
+
+Started in 2018, the project has evolved into a comprehensive suite of tools designed to help you create and consume RSS feeds effortlessly.
+
+---
+
+## Our Vision and Principles
+
+Our mission is to provide a simple, powerful, and accessible tool that enables individuals and developers to create custom RSS feeds from any web page. We believe in the power of open standards and the freedom to access information on your own terms.
+
+Our project is guided by these core principles:
+
+- **User Empowerment:** Giving you the tools to customize your web experience.
+- **Simplicity & Power:** Offering an easy-to-use interface with powerful underlying capabilities.
+- **Open Source:** Fostering a collaborative environment where the community can contribute and improve the project.
+- **Reliability:** Striving for a stable and dependable tool that consistently delivers.
+
+For insights into our ongoing development, project roadmap, and how you can get involved, please visit our [Get Involved]({{ '/get-involved' | relative_url }}) page.
+
+---
+
+### The Team
+
+`html2rss` is maintained by a dedicated group of volunteers and contributors from around the world. We are passionate about open source and committed to continuously improving the project.
+
+Want to join us? Check out our [Contributing Guide]({{ '/contributing' | relative_url }})!
diff --git a/assets/css/main.scss b/assets/css/main.scss
index 4495a031..c76854d5 100644
--- a/assets/css/main.scss
+++ b/assets/css/main.scss
@@ -8,6 +8,6 @@
// @import files directly from the sass/ directory:;
@import "base";
-
+@import "feed-directory";
// Don't write any SCSS in this file as stylelint does not fix it,
// just use the sass directory.
diff --git a/assets/css/sass/base.scss b/assets/css/sass/base.scss
index 14c8977c..9c95075f 100644
--- a/assets/css/sass/base.scss
+++ b/assets/css/sass/base.scss
@@ -16,85 +16,32 @@
--transition-shadow: box-shadow 0.2s ease-in-out;
}
-#configs input {
- width: 100%;
- padding: var(--spacing-xs);
- box-sizing: border-box;
- line-height: var(--line-height-base);
- font-size: var(--font-size-base);
- color: var(--color-text);
- font-family: var(--font-family-mono);
- background-color: transparent;
- border: 0;
- border-radius: 0;
- outline: none;
- appearance: none;
- -webkit-font-smoothing: antialiased;
- -moz-osx-font-smoothing: grayscale;
-}
-
-.config__headline > span,
-.config__url {
- hyphens: none;
- word-break: break-word;
- overflow-wrap: break-word;
- text-wrap: wrap;
+details {
+ transition: all 0.2s ease-in-out;
}
-.config__url em {
- padding-right: 0.125em;
- letter-spacing: -0.05em;
- opacity: 0.75;
- font-style: italic;
-}
-
-.config__url .config__url-amp:last-child {
- display: none !important;
+summary {
+ cursor: pointer;
+ outline: none;
}
-.js__copy-element {
- position: fixed;
- top: 0;
- left: 0;
- width: 0;
- height: 0;
- opacity: 0;
- pointer-events: none;
- user-select: text;
+summary:hover {
+ color: var(--link-color);
}
-.js__copy-element::selection {
- background-color: transparent;
+#configs input[name="instance"],
+#configs input[name="search"] {
+ inline-size: 100%;
}
.noscript {
+ padding: var(--spacing-sm);
font-weight: 600;
color: var(--color-error);
background: var(--color-error-bg);
- padding: var(--spacing-sm);
border: 1px solid var(--color-error);
}
-button[data-bind-click="copy"] {
- padding: var(--button-padding-y) var(--button-padding-x);
- border: 2px solid transparent;
- border-radius: var(--border-radius-sm);
- background-color: #fff;
- color: var(--color-text);
- cursor: pointer;
- font: inherit;
- line-height: 1.2;
- transition: var(--transition-border), var(--transition-shadow);
-}
-
-button[data-bind-click="copy"]:focus-visible {
- outline: 2px dashed var(--color-accent);
- outline-offset: 2px;
-}
-
-button[data-bind-click="copy"].copied,
-button[data-bind-click="copy"].copied:hover,
-button[data-bind-click="copy"].copied:active {
- border-color: var(--color-accent);
- box-shadow: inset 0 2px 4px var(--color-accent-bg);
+.svg-defs-hidden {
+ display: none;
}
diff --git a/assets/css/sass/feed-directory.scss b/assets/css/sass/feed-directory.scss
new file mode 100644
index 00000000..0da2a9ea
--- /dev/null
+++ b/assets/css/sass/feed-directory.scss
@@ -0,0 +1,138 @@
+.feed-directory__filters {
+ position: sticky;
+ top: 0;
+ height: fit-content;
+ z-index: 2;
+
+ border: 1px solid var(--border-color);
+ border-radius: var(--border-radius);
+ margin-bottom: var(--spacing-lg);
+ display: flex;
+ flex-wrap: wrap;
+ gap: var(--spacing-lg);
+ align-items: flex-start;
+}
+
+.feed-directory__item {
+ display: flex;
+ justify-content: space-between;
+ align-items: baseline;
+ gap: var(--spacing-sm);
+
+ padding: var(--spacing-sm);
+ border: 1px solid var(--border-color);
+ border-radius: var(--border-radius);
+
+ transition: var(--transition-base);
+}
+
+.feed-directory__item:hover {
+ box-shadow: var(--box-shadow);
+}
+
+.feed-directory__item-info {
+ display: flex;
+ flex-direction: column;
+ flex: 1;
+ gap: var(--spacing-xs);
+ margin-inline-end: var(--spacing-sm);
+}
+
+h3.feed-directory__item-name {
+ font-size: var(--font-size-h4);
+ font-weight: var(--font-weight-bold);
+ color: var(--color-text);
+ margin: 0;
+ padding: 0;
+}
+
+.feed-directory__item-url {
+ font-size: var(--font-size-sm);
+ color: var(--color-text-light);
+ word-break: break-word;
+ margin: 0;
+}
+
+.feed-directory__item-param-form__buttons {
+ display: flex;
+ justify-content: flex-end;
+}
+
+.feed-directory__item-actions {
+ display: flex;
+ align-items: center;
+ gap: var(--spacing-sm);
+ flex-shrink: 0;
+}
+
+.feed-directory__item-actions button {
+ background-color: unset;
+ border: 1px;
+ text-align: center;
+ padding: 0;
+ cursor: pointer;
+}
+
+.feed-directory__item-actions__rss-icon,
+.feed-directory__item-actions__edit-icon,
+.feed-directory__item-actions__settings-icon {
+ inline-size: 1.2rem;
+ block-size: 1.2rem;
+}
+
+.feed-directory__item-actions__rss-icon:hover,
+.feed-directory__item-actions__edit-icon:hover,
+.feed-directory__item-actions__settings-icon:hover {
+ color: var(--link-color);
+}
+
+.feed-directory__fieldset {
+ border: none;
+ padding: 0;
+ flex: 1 1 45%;
+ min-width: 280px;
+ margin-bottom: 0;
+}
+
+.feed-directory__fieldset legend {
+ padding: 0 var(--spacing-xs);
+ margin-bottom: var(--spacing-sm);
+}
+
+.feed-directory__item-param-form {
+ margin-block-start: var(--spacing-sm);
+ padding-block-start: var(--spacing-sm);
+ border-block-start: 1px solid var(--border-color);
+}
+
+.feed-directory__item-param-form__group {
+ margin-block-end: var(--spacing-xs);
+ display: flex;
+ align-items: center;
+ gap: var(--spacing-sm);
+}
+
+.feed-directory__item-param-form__label {
+ font-size: 0.85em;
+ font-weight: var(--font-weight-normal);
+ color: var(--color-text);
+ flex-shrink: 0;
+ min-width: 80px;
+}
+
+.feed-directory__item-param-form__input {
+ inline-size: 100%;
+ padding: var(--spacing-xs) var(--spacing-sm);
+ border: 1px solid var(--border-color);
+ border-radius: var(--border-radius-sm);
+ color: var(--color-text);
+}
+
+.feed-directory__item-param-form__code {
+ font-size: var(--font-size-sm);
+ padding: var(--spacing-xs) var(--spacing-sm);
+ border-radius: var(--border-radius-sm);
+ background-color: var(--code-block-bg-color);
+ color: var(--code-block-color);
+ word-break: break-all;
+}
diff --git a/assets/js/configs/index.js b/assets/js/configs/index.js
deleted file mode 100644
index b9deaa32..00000000
--- a/assets/js/configs/index.js
+++ /dev/null
@@ -1,59 +0,0 @@
-;(() => {
- const instanceEl = document.querySelector('input[name="instance"]')
-
- function instanceUrl() {
- const url = instanceEl.value
-
- return url.substr(-1) === "/" ? url : `${url}/`
- }
-
- function onChangeInstanceUrl() {
- const url = instanceUrl()
-
- Array.from(document.querySelectorAll(".instance")).forEach((el) => {
- el.innerText = url
- })
- }
-
- function onShowClick({ target }) {
- target.href = [instanceUrl(), target.dataset.path].join("")
- return false
- }
-
- function onCopyClick({ target }) {
- const href = [instanceUrl(), target.dataset.path].join("")
- const el = document.createElement("span")
- el.classList.add("js__copy-element")
- el.innerText = href
-
- document.body.appendChild(el)
- copyElementContents(el, target)
- return false
- }
-
- function copyElementContents(el, triggerEl) {
- el.focus()
- window.getSelection().selectAllChildren(el)
- document.execCommand("copy")
-
- triggerEl.classList.add("copied")
- window.setTimeout(() => {
- el.blur()
- el.remove()
- triggerEl.classList.remove("copied")
- triggerEl.blur()
- }, 1000)
- }
-
- // init
- document.querySelector("#configs").addEventListener("click", (event) => {
- if (event.target.dataset.bindClick === "show") {
- return onShowClick(event)
- } else if (event.target.dataset.bindClick === "copy") {
- return onCopyClick(event)
- }
- })
-
- instanceEl.addEventListener("blur", onChangeInstanceUrl)
- onChangeInstanceUrl()
-})()
diff --git a/assets/js/feed-directory/index.js b/assets/js/feed-directory/index.js
new file mode 100644
index 00000000..010b5457
--- /dev/null
+++ b/assets/js/feed-directory/index.js
@@ -0,0 +1,96 @@
+document.addEventListener("alpine:init", () => {
+ Alpine.data("feedDirectory", () => ({
+ instanceUrl: atob("aHR0cHM6Ly8xLmgyci53b3JrZXJzLmRldi8="),
+ searchQuery: "",
+ configs: window.feedDirectoryData,
+
+ fuzzyMatch(text, query) {
+ const lowerText = text.toLowerCase();
+ const lowerQuery = query.toLowerCase();
+ let textIndex = 0;
+ let queryIndex = 0;
+
+ while (queryIndex < lowerQuery.length && textIndex < lowerText.length) {
+ if (lowerQuery[queryIndex] === lowerText[textIndex]) {
+ queryIndex++;
+ }
+ textIndex++;
+ }
+ return queryIndex === lowerQuery.length;
+ },
+
+ filterConfig(configName) {
+ if (!this.searchQuery) {
+ return true;
+ }
+ return this.fuzzyMatch(configName, this.searchQuery);
+ },
+
+ getFeedUrl(config, params = {}) {
+ let url = this.instanceUrl.endsWith("/")
+ ? this.instanceUrl
+ : `${this.instanceUrl}/`;
+ url += `${config.domain}/${config.name}.rss`;
+
+ const queryParams = new URLSearchParams();
+
+ if (config.url_parameters) {
+ for (const key of Object.keys(config.url_parameters)) {
+ if (params[key]) {
+ queryParams.append(key, params[key]);
+ }
+ }
+ }
+
+ const queryString = queryParams.toString();
+ if (queryString) {
+ url += `?${queryString}`;
+ }
+
+ return url;
+ },
+ }));
+
+ Alpine.data("feedItemData", (index) => ({
+ config: window.feedDirectoryData[index],
+ params: {},
+ pathPreview: "",
+ showParamsForm: false,
+ toggleParamsForm() {
+ this.showParamsForm = !this.showParamsForm;
+ },
+ dynamicParamsInterpolate(string, params) {
+ return string.replace(/%<(\w+)>s/g, (_, key) => {
+ if (!(key in params)) {
+ throw new Error(`Missing value for placeholder: ${key}`);
+ }
+ return params[key];
+ });
+ },
+
+ init() {
+ if (!this.config) return;
+ if (!this.config.valid_channel_url) {
+ this.$watch("params", (value) => {
+ let params = {};
+
+ Object.entries(this.config.url_parameters).forEach(
+ ([key, fallback]) => {
+ const val = value[key];
+ params[key] = val || `{${fallback}}`;
+ },
+ );
+
+ try {
+ this.pathPreview = this.dynamicParamsInterpolate(
+ this.config.channel.url,
+ params,
+ );
+ } catch (error) {
+ console.error("Error interpolating parameters:", error);
+ }
+ });
+ }
+ },
+ }));
+});
diff --git a/assets/js/main.js b/assets/js/main.js
index a4385c4b..2f7bb21c 100644
--- a/assets/js/main.js
+++ b/assets/js/main.js
@@ -7,8 +7,8 @@
// async
// >
-;(() => {
+(() => {
document.addEventListener("DOMContentLoaded", () => {
// do stuff
- })
-})()
+ });
+})();
diff --git a/components/html2rss-configs.md b/components/html2rss-configs.md
deleted file mode 100644
index 89c3ca17..00000000
--- a/components/html2rss-configs.md
+++ /dev/null
@@ -1,23 +0,0 @@
----
-layout: default
-parent: Components
-nav_order: 3
-title: html2rss-configs
-description: html2rss-configs is a a growing repository of html2rss feed configs.
-summary: a repository of feed configs
----
-
-{{ page.description }}
-{: .fs-8 }
-
----
-
-The [html2rss-config](https://github.com/html2rss/html2rss-configs) repository contains feed configs. Each feed config contains the instructions for the html2rss gem on how to build the RSS feed. Thus, to create a config, you need write CSS selectors and express them in YAML.
-
-The feed config must reside in a folder named after the fully qualified domain name of the website.
-
-The repository has its own test suite. It automatically tests each config and requires them to adhere to the conventions.
-
-A generator scaffolds a feed config and a test for that config. It gets you started in a breeze and let's you focus on writing the selectors.
-
-[See the project on Github](https://github.com/html2rss/html2rss-configs){: .btn .btn-purple }
diff --git a/components/html2rss-web.md b/components/html2rss-web.md
deleted file mode 100644
index fca49e3a..00000000
--- a/components/html2rss-web.md
+++ /dev/null
@@ -1,28 +0,0 @@
----
-layout: default
-parent: Components
-nav_order: 2
-title: html2rss-web
-description: html2rss-web app is a small application which serves RSS feeds via HTTP.
-summary: serves RSS feeds via HTTP
----
-
-{{ page.description }}
-{: .fs-8 }
-
----
-
-html2rss-web builds and serves RSS feeds via HTTP. It's a small application which serves feeds via HTTP. It uses the _feed configs_ from [html2rss-configs](./html2rss-configs) and expose the _html2rss_ generated feeds via HTTP.
-
-**Generate your own feeds, or start instantly with the included configs.**
-
-- It's deployable without much hassle (also via Docker).
-- It has a file-based application cache to prevent _hammering_ websites
-- It handles with client-side HTTP cache headers.
-
-
- Everyone can host their own html2rss-web instance.
- There are [public instances](https://github.com/html2rss/html2rss-web/wiki/Instances) for those who can't.
-
-
-[See the project on Github](https://github.com/html2rss/html2rss-web){: .btn .btn-purple }
diff --git a/components/html2rss.md b/components/html2rss.md
deleted file mode 100644
index 084c9ca2..00000000
--- a/components/html2rss.md
+++ /dev/null
@@ -1,32 +0,0 @@
----
-layout: default
-parent: Components
-nav_order: 1
-title: html2rss gem
-description: html2rss build RSS 2.0 feeds from websites (and JSON APIs) with a few CSS selectors.
-summary: a Ruby gem to build RSS 2.0 feeds
----
-
-{{ page.description }}
-{: .fs-8 }
-
----
-
-The [html2rss gem](https://rubygems.org/gems/html2rss) generates a Ruby RSS object from a _feed config_. It does so by scraping and extracting the website.
-
-Scraping involves a tad more than just selecting an HTML element's text contents.
-
-- You want to sanitize HTML.
-- You might find useful information in a `data` attribute in the page's source.
-- You need to convert relative URLs to absolute ones.
-- You want to parse dates & times in the publishers' time zone.
-- Maybe the website is a JSON API and you want that response converted to a RSS feed?
-- You might need to send requests with Authorization or Cookie HTTP headers.
-- You want to scrape several syntactically equal pages on one website without duplicating the configs.
-- You want to create a custom item description from other attributes.
-
-The documentation covers everything the gem is capable of. If you want to dive deeper, read the [gem's README](https://github.com/html2rss/html2rss/blob/master/README.md) or check [the YARD Docs](https://www.rubydoc.info/gems/html2rss).
-
-The gem's code is automatically tested. There's also code documentation for the API, usually with examples. However, looking inside the test suite to find to find more complex examples is recommended.
-
-[See the project on Github](https://github.com/html2rss/html2rss){: .btn .btn-purple }
diff --git a/configs.md b/configs.md
new file mode 100644
index 00000000..b1cab598
--- /dev/null
+++ b/configs.md
@@ -0,0 +1,13 @@
+---
+permalink: /configs/
+---
+
+
+
+
+
+
+
+
- This config requires parameters to work.
- View the config
- to find out which values are possible.
-
-
- {{ config.domain }}/{{ config.name }}.rss?{% for params in config.url_parameters %}{{ params[0] }}={{ params[1] }}&{% endfor %}
-
-
-
- {%- endif -%}
-
-{% endfor %}
-
-
-
diff --git a/contributing.md b/contributing.md
deleted file mode 100644
index a608129d..00000000
--- a/contributing.md
+++ /dev/null
@@ -1,25 +0,0 @@
----
-layout: default
-title: Contributing
-nav_order: 10
----
-
-There are many ways to contribute. Contributions are very welcome!
-
-## Create a feed config
-
-Are you missing an RSS for a site? Create your config and add make it available in the ecosystem. [It's easy, just have a look and try it out!](https://github.com/html2rss/html2rss-configs)
-
-## Improve this website
-
-This website is build with Jekyll and Github Actions. [Find the source code here.](https://github.com/html2rss/html2rss.github.io)
-
-## Host your own public instance
-
-The [html2rss-web project](https://github.com/html2rss/html2rss-web) is a rolling release web application which comes with the latest html2rss-configs build in.
-
-Setup and maintain your instance. Do not forget to add your instance to [the instances list in the wiki](https://github.com/html2rss/html2rss-web/wiki/Instances) so that others can start using it.
-
-## Improve the html2rss gem
-
-Are you missing a feature in the [html2rss gem](https://github.com/html2rss/html2rss)? Did you find a bug? Head to the [repository on Github](https://github.com/html2rss/html2rss) and start working on it.
diff --git a/feed-directory/index.html b/feed-directory/index.html
new file mode 100644
index 00000000..2aeef3a8
--- /dev/null
+++ b/feed-directory/index.html
@@ -0,0 +1,222 @@
+---
+layout: default
+title: Feed Directory
+nav_order: 2
+noindex: true
+---
+
+
+
Welcome to the Feed Directory!
+
+ This directory contains a list of pre-built configurations to create RSS
+ feeds for various websites.
+
+
+
+
+
Instance URL
+
+ An "Instance URL" is the address of a running
+ html2rss-web application. You can use a public instance, but we
+ encourage you to host your own.
+
+ The feed configurations in this directory are community-driven. If you've
+ created a new feed configuration, we encourage you to share it with the
+ community.
+
+
+
+
diff --git a/get-involved/contributing.md b/get-involved/contributing.md
new file mode 100644
index 00000000..40cb43e1
--- /dev/null
+++ b/get-involved/contributing.md
@@ -0,0 +1,64 @@
+---
+layout: default
+title: Contributing
+parent: Get Involved
+nav_order: 10
+---
+
+# Contributing to html2rss
+
+We're thrilled that you're interested in contributing to `html2rss`! There are many ways to get involved, and we welcome contributions of all kinds.
+
+---
+
+## Code of Conduct
+
+Before you begin, please read our [Code of Conduct](https://github.com/html2rss/.github/blob/main/CODE_OF_CONDUCT.md). We expect all contributors to adhere to this code to ensure that our community is a welcoming and inclusive space for everyone.
+
+---
+
+## How to Contribute
+
+Here are some of the ways you can contribute to the `html2rss` project:
+
+### 1. Create a Feed Config
+
+Are you missing an RSS feed for a website? You can create your own feed config and share it with the community. It's a great way to get started with `html2rss` and help other users.
+
+[**Learn how to create a feed config**](https://github.com/html2rss/html2rss-configs)
+
+### 2. Improve this Website
+
+This website is built with Jekyll and is hosted on GitHub Pages. If you have any ideas for improving the documentation or the design, we'd love to hear from you.
+
+[**Find the source code on GitHub**](https://github.com/html2rss/html2rss.github.io)
+
+### 3. Host a Public Instance
+
+The [`html2rss-web`](https://github.com/html2rss/html2rss-web) project is a web application that allows you to create and manage your RSS feeds through a user-friendly interface. You can host your own public instance to help other users create feeds.
+
+[**Learn how to host a public instance**](https://github.com/html2rss/html2rss-web/wiki/Instances)
+
+### 4. Improve the `html2rss` Gem
+
+Are you a Ruby developer? You can help us improve the core `html2rss` gem. Whether you're fixing a bug, adding a new feature, or improving the documentation, your contributions are welcome.
+
+[**Check out the repository on GitHub**](https://github.com/html2rss/html2rss)
+
+### 5. Report Bugs & Discuss Features
+
+If you've found a bug, please open an issue on the appropriate GitHub repository. For new feature ideas, we encourage you to start a discussion first.
+
+**Report Bugs:**
+
+- [**`html2rss` issues**](https://github.com/html2rss/html2rss/issues)
+- [**`html2rss-web` issues**](https://github.com/html2rss/html2rss-web/issues)
+- [**`html2rss-configs` issues**](https://github.com/html2rss/html2rss-configs/issues)
+
+**Discuss Features:**
+
+- [**Start a New Discussion on GitHub**](https://github.com/orgs/html2rss/discussions)
+
+---
+
+We appreciate your interest in contributing to `html2rss`!
diff --git a/get-involved/discussions.md b/get-involved/discussions.md
new file mode 100644
index 00000000..3025e5f5
--- /dev/null
+++ b/get-involved/discussions.md
@@ -0,0 +1,14 @@
+---
+layout: default
+title: Join Community Discussions
+nav_order: 2
+parent: Get Involved
+---
+
+# Join Community Discussions
+
+Connect with other users and contributors by joining our community discussions on GitHub. This is a vibrant space for general questions, sharing tips, discussing ideas, and getting feedback from the community.
+
+[**💬 Join Discussions on GitHub**](https://github.com/orgs/html2rss/discussions)
+
+We encourage you to participate, ask questions, and share your insights!
diff --git a/get-involved/index.md b/get-involved/index.md
new file mode 100644
index 00000000..787ad020
--- /dev/null
+++ b/get-involved/index.md
@@ -0,0 +1,17 @@
+---
+layout: default
+title: Get Involved
+nav_order: 5
+has_children: true
+---
+
+# Get Involved
+
+- [**Sponsoring**]({{ '/get-involved/sponsoring' | relative_url }})
+
+Engage with the `html2rss` project. Contribute and connect with the community.
+
+- [**Project Roadmap**]({{ 'https://github.com/orgs/html2rss/projects/3/views/1' }}): View current work, plans, and priorities.
+- [**Report Bugs & Discuss Features**]({{ '/get-involved/issues-and-features' | relative_url }}): Report bugs or propose features.
+- [**Join Community Discussions**]({{ '/get-involved/discussions' | relative_url }}): Connect with users and contributors.
+- [**Contribute to html2rss**]({{ '/contributing' | relative_url }}): Contribute code, documentation, or feed configurations.
diff --git a/get-involved/issues-and-features.md b/get-involved/issues-and-features.md
new file mode 100644
index 00000000..7cd9611a
--- /dev/null
+++ b/get-involved/issues-and-features.md
@@ -0,0 +1,37 @@
+---
+layout: default
+title: Report Bugs & Discuss Features
+nav_order: 1
+parent: Get Involved
+---
+
+# Report Bugs & Discuss Features
+
+We appreciate your help in improving `html2rss`! Please follow these guidelines when reporting issues or suggesting new features.
+
+---
+
+### Reporting Bugs
+
+If you've found a bug, please open an issue on the appropriate GitHub repository. This helps us track and resolve problems efficiently.
+
+[**➡️ Open an Issue on GitHub**](https://github.com/html2rss/html2rss/issues)
+
+When opening a bug report, please provide as much detail as possible, including:
+
+- The `html2rss` version you are using.
+- Your operating system.
+- Your configuration file (if applicable).
+- The target URL you are trying to scrape.
+- Any error messages you receive.
+- Steps to reproduce the issue.
+
+---
+
+### Discussing New Features
+
+For new feature ideas or enhancements, we encourage you to start a discussion on GitHub Discussions first. This allows for community input, refinement of the idea, and helps us prioritize development.
+
+[**💬 Start a New Discussion on GitHub**](https://github.com/orgs/html2rss/discussions)
+
+If the discussion leads to a concrete proposal, a formal feature request issue can then be opened.
diff --git a/get-involved/sponsoring.md b/get-involved/sponsoring.md
new file mode 100644
index 00000000..8b39384a
--- /dev/null
+++ b/get-involved/sponsoring.md
@@ -0,0 +1,20 @@
+---
+layout: default
+title: Sponsoring
+parent: Get Involved
+nav_order: 4
+---
+
+# Sponsoring html2rss
+
+`html2rss` is an open-source project, and its development is made possible by the support of our community. If you find `html2rss` useful, please consider sponsoring the project.
+
+## Why Sponsor?
+
+- **Ensure the project's longevity:** Your sponsorship helps to ensure that the project remains actively maintained and developed.
+- **Support new features:** Your contribution will help to fund the development of new features and improvements.
+- **Show your appreciation:** Sponsoring is a great way to show your appreciation for the project and the work that goes into it.
+
+## How to Sponsor
+
+You can sponsor the project through [GitHub Sponsors](https://github.com/sponsors/gildesmarais).
diff --git a/index.html b/index.html
deleted file mode 100644
index 8bf05453..00000000
--- a/index.html
+++ /dev/null
@@ -1,25 +0,0 @@
----
-layout: default
-title: html2rss - Home
-nav_order: 0
----
-
-
html2rss builds RSS feeds from websites which do not have one.
-
- Start using RSS feeds right away or find out what html2rss has to offer.
-
- View the feeds
- How it works
-
-
-
-
-html2rss is a ecosystem of components with the goals to:
-
-
-
generate RSS feeds by scraping websites (and JSON APIs).
-
make it easy to build and use a feed config.
-
have multiple decentralized and always up to date instances.
-
-
-Read more about the involved components.
diff --git a/index.md b/index.md
new file mode 100644
index 00000000..d8ae1254
--- /dev/null
+++ b/index.md
@@ -0,0 +1,33 @@
+---
+layout: default
+title: Home
+nav_order: 1
+---
+
+# Create RSS Feeds for Any Website
+
+`html2rss` creates RSS feeds for any website.
+[**🚀 Get Started with the Web App**]({{ '/web-application/getting-started' | relative_url }})
+
+---
+
+## Key Features
+
+- **Automatic Feed Generation:** `auto_source` intelligently extracts content, simplifying feed creation.
+- **Precise Content Extraction:** Use CSS selectors for targeted content inclusion.
+- **JavaScript Rendering:** A headless browser renders JavaScript-heavy sites for comprehensive content extraction.
+- **Open Source:** `html2rss` is free to use, modify, and contribute.
+
+---
+
+## The html2rss Ecosystem
+
+The `html2rss` project offers a complete RSS solution through a collection of integrated tools:
+
+- **[html2rss-web]({{ '/web-application' | relative_url }}):** User-friendly web application to create, manage, and share RSS feeds. Recommended starting point.
+- **[html2rss (Ruby Gem)]({{ '/ruby-gem' | relative_url }}):** Core library and command-line interface for developers.
+- **[Feed Directory]({{ '/feed-directory' | relative_url }}):** Public listing of community-driven RSS feed configurations.
+
+---
+
+Engage with the `html2rss` community or contribute. Visit our [Get Involved]({{ '/get-involved' | relative_url }}) page.
diff --git a/package.json b/package.json
index f4e07a15..b942234a 100644
--- a/package.json
+++ b/package.json
@@ -2,13 +2,20 @@
"license": "UNLICENSED",
"private": true,
"scripts": {
- "lintfix": "stylelint --fix assets/**/*.scss"
+ "lint": "yarn lint:stylelint && yarn lint:prettier",
+ "lint:stylelint": "stylelint assets/**/*.scss",
+ "lint:prettier": "prettier --check .",
+ "lintfix": "yarn lintfix:stylelint && yarn lintfix:prettier",
+ "lintfix:stylelint": "stylelint --fix assets/**/*.scss",
+ "lintfix:prettier": "prettier --write ."
},
"devDependencies": {
- "stylelint": "16.22.0",
+ "prettier": "3.6.2",
+ "stylelint": "16.23.0",
"stylelint-config-recess-order": "7.1.0",
+ "stylelint-order": "7.0.0",
"stylelint-config-recommended-scss": "15.0.1",
"stylelint-scss": "6.12.1"
},
- "packageManager": "yarn@1.22.19+sha1.4ba7fc5c6e704fce2066ecbfb0b0d8976fe62447"
+ "packageManager": "yarn@1.22.22"
}
diff --git a/ruby-gem/how-to/advanced-content-extraction.md b/ruby-gem/how-to/advanced-content-extraction.md
new file mode 100644
index 00000000..7d5845af
--- /dev/null
+++ b/ruby-gem/how-to/advanced-content-extraction.md
@@ -0,0 +1,19 @@
+---
+layout: default
+title: Advanced Content Extraction
+nav_order: 3
+parent: How-To Guides
+grand_parent: Ruby Gem
+---
+
+# Advanced Content Extraction with Selectors
+
+While basic selectors are straightforward, you can achieve very precise content extraction by combining selectors with different extractors and post-processors.
+
+## Extractors
+
+Learn how to extract specific attributes (like `src` for images) or static values. See [Extractors]({{ '/ruby-gem/reference/selectors/extractors' | relative_url }}).
+
+## Post Processors
+
+Manipulate extracted text, sanitize HTML, convert Markdown, or apply custom logic. See [Post Processors]({{ '/ruby-gem/reference/selectors/post-processors' | relative_url }}).
diff --git a/ruby-gem/how-to/custom-http-requests.md b/ruby-gem/how-to/custom-http-requests.md
new file mode 100644
index 00000000..4885f7c7
--- /dev/null
+++ b/ruby-gem/how-to/custom-http-requests.md
@@ -0,0 +1,15 @@
+---
+layout: default
+title: Custom HTTP Requests
+nav_order: 4
+parent: How-To Guides
+grand_parent: Ruby Gem
+---
+
+# Customizing HTTP Requests
+
+You might need to send custom HTTP headers (e.g., `User-Agent`, `Authorization`) to access certain content or interact with APIs.
+
+## Solution
+
+Configure [custom HTTP headers]({{ '/ruby-gem/reference/headers' | relative_url }}) in your feed configuration.
diff --git a/ruby-gem/how-to/dynamic-parameters.md b/ruby-gem/how-to/dynamic-parameters.md
new file mode 100644
index 00000000..b3d1f2cb
--- /dev/null
+++ b/ruby-gem/how-to/dynamic-parameters.md
@@ -0,0 +1,36 @@
+---
+layout: default
+title: Dynamic Parameters
+nav_order: 5
+parent: How-To Guides
+grand_parent: Ruby Gem
+---
+
+# Dynamic Parameters in URLs and Headers
+
+For websites with similar structures but varying content based on a parameter in the URL or headers, you can use dynamic parameters.
+
+## Solution
+
+You can add dynamic parameters to the `channel` and `headers` values. This is useful for creating feeds from structurally similar pages with different URLs.
+
+```yaml
+channel:
+ url: "http://domainname.tld/whatever/%s.html"
+headers:
+ X-Something: "%s"
+```
+
+You can then pass the values for these parameters when you run `html2rss`:
+
+```bash
+html2rss feed the_feed_config.yml --params id:42 foo:bar
+```
+
+---
+
+## Explanation
+
+- The `%s` syntax in the URL and headers is a placeholder for dynamic parameters.
+- You provide the actual values for these parameters at runtime using the `--params` option.
+- This allows you to reuse the same feed configuration for multiple similar pages or APIs.
diff --git a/ruby-gem/how-to/handling-dynamic-content.md b/ruby-gem/how-to/handling-dynamic-content.md
new file mode 100644
index 00000000..4148a2e5
--- /dev/null
+++ b/ruby-gem/how-to/handling-dynamic-content.md
@@ -0,0 +1,15 @@
+---
+layout: default
+title: Handling Dynamic Content
+nav_order: 6
+parent: How-To Guides
+grand_parent: Ruby Gem
+---
+
+# Handling Dynamic Content and JavaScript
+
+Some websites load their content dynamically using JavaScript. The default `html2rss` strategy might not see this content.
+
+## Solution
+
+Use the [`browserless` strategy]({{ '/ruby-gem/reference/strategy' | relative_url }}) to render JavaScript-heavy websites with a headless browser.
diff --git a/ruby-gem/how-to/index.md b/ruby-gem/how-to/index.md
new file mode 100644
index 00000000..9cdcd8be
--- /dev/null
+++ b/ruby-gem/how-to/index.md
@@ -0,0 +1,11 @@
+---
+layout: default
+title: How-To Guides
+parent: Ruby Gem
+nav_order: 2
+has_children: true
+---
+
+# How-To Guides
+
+This section provides practical examples and solutions for common tasks when using the `html2rss` gem.
diff --git a/ruby-gem/how-to/managing-feed-configs.md b/ruby-gem/how-to/managing-feed-configs.md
new file mode 100644
index 00000000..7509bb3b
--- /dev/null
+++ b/ruby-gem/how-to/managing-feed-configs.md
@@ -0,0 +1,63 @@
+---
+layout: default
+title: Managing Feed Configs
+parent: How-To Guides
+grand_parent: Ruby Gem
+nav_order: 7
+---
+
+# Managing Feed Configurations with YAML
+
+For easier management, especially when using the CLI or `html2rss-web`, you can store your feed configurations in a YAML file.
+
+## Global and Feed-Specific Configurations
+
+You can define global settings that apply to all feeds, and then define individual feed configurations under the `feeds` key.
+
+```yml
+# Global settings
+headers:
+ "User-Agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 10_3_1 like Mac OS X) AppleWebKit/603.1.30 (KHTML, like Gecko) Version/10.0 Mobile/14E304 Safari/602.1"
+ "Accept": "text/html"
+
+# Feed-specific settings
+feeds:
+ my-first-feed:
+ channel:
+ url: "https://example.com/blog"
+ selectors:
+ # ...
+ my-second-feed:
+ channel:
+ url: "https://example.com/news"
+ selectors:
+ # ...
+```
+
+## Building Feeds from a YAML File
+
+### Ruby
+
+```ruby
+require 'html2rss'
+
+# Build a specific feed from the YAML file
+my_feed_config = Html2rss.config_from_yaml_file('feeds.yml', 'my-first-feed')
+rss = Html2rss.feed(my_feed_config)
+puts rss
+
+# If the YAML file contains only one feed, you can omit the feed name
+single_feed_config = Html2rss.config_from_yaml_file('single.yml')
+rss = Html2rss.feed(single_feed_config)
+puts rss
+```
+
+### Command Line
+
+```sh
+# Build a specific feed
+html2rss feed feeds.yml my-first-feed
+
+# Build a feed from a single-feed YAML file
+html2rss feed single.yml
+```
diff --git a/ruby-gem/how-to/scraping-json.md b/ruby-gem/how-to/scraping-json.md
new file mode 100644
index 00000000..47c3438f
--- /dev/null
+++ b/ruby-gem/how-to/scraping-json.md
@@ -0,0 +1,94 @@
+---
+layout: default
+title: Scraping JSON Responses
+parent: How-To Guides
+grand_parent: Ruby Gem
+nav_order: 6
+---
+
+# Scraping JSON Responses
+
+When a website returns a JSON response (i.e., with a `Content-Type` of `application/json`), `html2rss` converts the JSON to XML, allowing you to use CSS selectors for data extraction.
+
+> [!NOTE]
+> The JSON response must be an Array or a Hash for the conversion to work.
+
+## JSON to XML Conversion Examples
+
+### JSON Object
+
+A JSON object like this:
+
+```json
+{
+ "data": [{ "title": "Headline", "url": "https://example.com" }]
+}
+```
+
+is converted to this XML structure:
+
+```xml
+
+```
+
+You would use `array > object` as your `items` selector.
+
+### JSON Array
+
+A JSON array like this:
+
+```json
+[{ "title": "Headline", "url": "https://example.com" }]
+```
+
+is converted to this XML structure:
+
+```xml
+
+
+ Headline
+ https://example.com
+
+
+```
+
+You would use `array > object` as your `items` selector.
+
+## Configuration Examples
+
+### Ruby
+
+```ruby
+Html2rss.feed(
+ headers: {
+ Accept: 'application/json'
+ },
+ channel: {
+ url: 'http://domainname.tld/whatever.json'
+ },
+ selectors: {
+ title: { selector: 'foo' }
+ }
+)
+```
+
+### YAML
+
+```yml
+headers:
+ Accept: application/json
+channel:
+ url: "http://domainname.tld/whatever.json"
+selectors:
+ title:
+ selector: "foo"
+```
diff --git a/ruby-gem/how-to/styling-rss-feed.md b/ruby-gem/how-to/styling-rss-feed.md
new file mode 100644
index 00000000..9e417211
--- /dev/null
+++ b/ruby-gem/how-to/styling-rss-feed.md
@@ -0,0 +1,15 @@
+---
+layout: default
+title: Styling Your RSS Feed
+nav_order: 7
+parent: How-To Guides
+grand_parent: Ruby Gem
+---
+
+# Styling Your RSS Feed
+
+You can make your RSS feed look good in a web browser by attaching stylesheets.
+
+## Solution
+
+Add [stylesheets]({{ '/ruby-gem/reference/stylesheets' | relative_url }}) to your feed configuration.
diff --git a/ruby-gem/index.md b/ruby-gem/index.md
new file mode 100644
index 00000000..b208cd33
--- /dev/null
+++ b/ruby-gem/index.md
@@ -0,0 +1,20 @@
+---
+layout: default
+title: Ruby Gem
+nav_order: 3
+has_children: true
+---
+
+# The html2rss Ruby Gem
+
+This section provides comprehensive documentation for the `html2rss` Ruby gem.
+
+## Getting Started
+
+If you are new to `html2rss`, we recommend starting with the [tutorials]({{ '/ruby-gem/tutorials' | relative_url }}).
+
+## Documentation Sections
+
+- **[Tutorials]({{ '/ruby-gem/tutorials' | relative_url }})**: Step-by-step guides to help you get started with `html2rss`.
+- **[How-To Guides]({{ '/ruby-gem/how-to' | relative_url }})**: Practical examples and solutions for common tasks.
+- **[Reference]({{ '/ruby-gem/reference' | relative_url }})**: Detailed information on configuration options.
diff --git a/ruby-gem/installation.md b/ruby-gem/installation.md
new file mode 100644
index 00000000..101dce22
--- /dev/null
+++ b/ruby-gem/installation.md
@@ -0,0 +1,72 @@
+---
+layout: default
+title: Installation
+nav_order: 1
+parent: Ruby Gem
+---
+
+# Installation
+
+This guide will walk you through the process of installing html2rss on your system. html2rss can be installed in several ways, depending on your preferred method and environment.
+
+---
+
+### Prerequisites
+
+- **Ruby:** html2rss is built with Ruby. Ensure you have Ruby installed (version 3.3 or higher recommended). You can check your Ruby version by running `ruby -v` in your terminal. If you don't have Ruby, visit [ruby-lang.org](https://www.ruby-lang.org/en/documentation/installation/) for installation instructions.
+- **Bundler (Recommended):** Bundler is a Ruby gem that manages your application's dependencies. It's highly recommended for a smooth installation. Install it with `gem install bundler`.
+
+---
+
+### Method 1: Gem Installation (Recommended for CLI Usage)
+
+The simplest way to get html2rss for command-line usage is to install it as a Ruby gem.
+
+```bash
+gem install html2rss
+```
+
+After installation, you should be able to run `html2rss --version` to confirm it's working.
+
+---
+
+### Method 2: Using a Gemfile (For Ruby Projects)
+
+If you're integrating html2rss into an existing Ruby project, add it to your `Gemfile`:
+
+```ruby
+# Gemfile
+gem 'html2rss'
+```
+
+Then, run `bundle install` in your project directory.
+
+---
+
+### Method 3: Docker (For Containerized Environments)
+
+For a more isolated and reproducible environment, you can use the official html2rss Docker image.
+
+```bash
+docker pull html2rss/html2rss
+```
+
+You can then run html2rss commands within a Docker container. Refer to the [Docker Hub page](https://hub.docker.com/r/html2rss/html2rss) for detailed usage.
+
+---
+
+### Verifying Installation
+
+To ensure html2rss is installed correctly, open your terminal and run:
+
+```bash
+html2rss --version
+```
+
+You should see the installed version number. If you encounter any issues, please refer to the [Troubleshooting Guide]({{ "/support/troubleshooting" | relative_url }}).
+
+---
+
+### Next Steps
+
+Now that html2rss is installed, let's create your [first RSS feed]({{ '/ruby-gem/tutorials/your-first-feed' | relative_url }})!
diff --git a/ruby-gem/reference/auto-source.md b/ruby-gem/reference/auto-source.md
new file mode 100644
index 00000000..ffac4f36
--- /dev/null
+++ b/ruby-gem/reference/auto-source.md
@@ -0,0 +1,59 @@
+---
+layout: default
+title: Auto Source
+nav_order: 5
+parent: Reference
+grand_parent: Ruby Gem
+---
+
+# Auto Source
+
+The `auto_source` scraper automatically finds items on a page, so you don't have to specify CSS selectors.
+
+To enable it, add `auto_source: {}` to your configuration:
+
+```yaml
+channel:
+ url: https://example.com
+auto_source: {}
+```
+
+## How It Works
+
+`auto_source` uses the following strategies to find content:
+
+1. **`schema`:** Parses `