Skip to content
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ pnpm-debug.log*
# environment variables
.env
.env.production
!examples/deployment/.env

# macOS-specific files
.DS_Store
94 changes: 94 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
# Repository Guidelines

## Scope and Ownership

This repository (`html2rss.github.io/`) is the public docs and feed-directory site built with Astro/Starlight.
Classify most work here as `docs`.

What this repo owns:

- docs content and navigation under `src/content/docs/`
- docs-specific components and styling under `src/components/`
- feed-directory presentation and client behavior
- generated docs data consumed by the site (`src/data/configs.json`)

What this repo does not own:

- runtime extractor behavior and CLI semantics (`html2rss/`)
- web API behavior and OpenAPI generation (`html2rss-web/`)
- feed YAML catalog definitions (`html2rss-configs/`)

When docs describe behavior from other repos, treat those repos as source-of-truth and update docs to match them.

## Cross-Repo Contracts

Before substantial edits, state cross-repo context in your notes:

- Source-of-truth repo
- Downstream consumer repo(s)
- Whether this change needs coordinated follow-up outside `html2rss.github.io/`

Common contracts:

- Feed directory data comes from `html2rss-configs` via `bin/data-update`.
- Ruby gem docs should match `html2rss` behavior and CLI output.
- Web application docs should match `html2rss-web` behavior and published OpenAPI.

If a cross-repo behavior changed but upstream is not updated yet, document the gap clearly instead of inventing new behavior.

## Generated Artifacts

Treat `src/data/configs.json` as generated.

- Do not hand-edit it.
- Regenerate with repo-native commands:
- `make update`
- or `bin/data-update` (after dependencies are installed)
- `bin/data-update` reads packaged configs (from `html2rss-configs`) and writes `src/data/configs.json`.

If a change only affects generated data, include the source change rationale in the PR description.

## Build, Test, and Dev Commands

Run commands from `html2rss.github.io/`:

- `make setup` installs dependencies and refreshes generated data
- `make dev` runs Astro locally
- `make build` builds production output
- `make lint` checks formatting
- `make lintfix` applies formatting fixes
- `make update` refreshes feed-directory data from packaged configs

Preferred verification flow for docs/content changes:

1. Run targeted check(s) first (`make lint` or `make build`).
2. Run the broader check set before PR (`make lint` and `make build`).
3. If feed directory or config references changed, run `make update` and verify resulting diffs.

## Docs Authoring Rules

### Code Snippets

In docs content (`src/content/docs/**`) and docs-supporting components:

- Do not use triple-backtick fenced code blocks.
- Always render snippets with the `<Code>` component.
- Use this import:
`import { Code } from '@astrojs/starlight/components';`
- Do not use:
`import Code from "astro/components/Code.astro";`

### Accuracy Rules

- Prefer concrete, verifiable statements over aspirational wording.
- Keep repo and path references explicit when guidance is cross-repo.
- When referencing commands that belong to another repo, include that repo directory in the command example.

## Commit and PR Expectations

- Keep each commit scoped to one logical docs change.
- Do not mix unrelated changes or unrelated generated diffs.
- In PRs, call out:
- cross-repo assumptions
- generated files updated
- verification commands run
13 changes: 7 additions & 6 deletions Gemfile.lock
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
GIT
remote: https://github.com/html2rss/html2rss-configs.git
revision: 2d64c4766e12835d64b6ecaa46ee23491a2be4a2
revision: 24d38d64e578e93340e228c7bbfd2b187a2b94b6
specs:
html2rss-configs (0.2.0)
html2rss

GIT
remote: https://github.com/html2rss/html2rss.git
revision: 2e0fa0ca5835cc49268a85f7ad79e2a5b33b4b79
revision: 04720b83c69f8b2fcf6d9ba7f360b84f6bcb5fe6
specs:
html2rss (0.17.0)
addressable (~> 2.7)
Expand Down Expand Up @@ -59,7 +59,7 @@ GEM
protocol-rack (~> 0.7)
protocol-websocket (~> 0.17)
base64 (0.3.0)
bigdecimal (4.0.1)
bigdecimal (4.1.0)
brotli (0.8.0)
concurrent-ruby (1.3.6)
console (1.34.3)
Expand Down Expand Up @@ -118,9 +118,9 @@ GEM
fiber-storage
fiber-storage (1.0.1)
io-endpoint (0.17.2)
io-event (1.14.4)
io-event (1.14.5)
io-stream (0.11.1)
json (2.19.2)
json (2.19.3)
kramdown (2.5.2)
rexml (>= 3.4.4)
logger (1.7.0)
Expand Down Expand Up @@ -178,11 +178,12 @@ GEM

PLATFORMS
arm64-darwin-24
arm64-darwin-25
x86_64-linux

DEPENDENCIES
html2rss!
html2rss-configs!

BUNDLED WITH
2.7.1
4.0.9
9 changes: 6 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,21 +13,24 @@ website.
### Quick Setup

```bash
# Install dependencies and start development server
# Install dependencies and refresh generated feed data
make setup

# Start the local Astro development server
make dev
```

### 💻 Try in Browser

You can develop html2rss directly in your browser using GitHub Codespaces:

[Open in GitHub Codespaces](https://github.com/codespaces/new?repo=html2rss/html2rss)
[Open in GitHub Codespaces](https://github.com/codespaces/new?repo=html2rss/html2rss.github.io)

The Codespace provides a cloud development environment with Node.js and Ruby pre-installed. Run `make setup` to install dependencies and get started!

### Available Commands

- `make setup` - Install dependencies and start dev server
- `make setup` - Install dependencies and refresh generated feed data
- `make dev` - Start Astro development server
- `make build` - Build for production
- `make preview` - Preview production build
Expand Down
26 changes: 26 additions & 0 deletions examples/deployment/.env
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Domain & routing
CADDY_HOST=example.com

# Core runtime
RACK_ENV=production

# Security
# Generate with: openssl rand -hex 32
HTML2RSS_SECRET_KEY=replace-with-64-hex-characters-generated-by-openssl-rand-hex-32

# Authenticated health endpoint token
# Required by the documented Compose stack.
# If you build a custom stack and probe only /api/v1/health/live and /api/v1/health/ready,
# you can omit this value.
HEALTH_CHECK_TOKEN=replace-with-strong-health-token

# Auto source (optional; keep false unless you need automatic feed generation)
AUTO_SOURCE_ENABLED=false

# Observability (optional)
#SENTRY_DSN=

# Performance tuning (override defaults only when needed)
WEB_CONCURRENCY=2
WEB_MAX_THREADS=5
RACK_TIMEOUT_SERVICE_TIMEOUT=15
19 changes: 11 additions & 8 deletions examples/deployment/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,19 +1,24 @@
services:
html2rss:
html2rss-web:
image: html2rss/web:latest
env_file: .env
restart: unless-stopped
env_file:
- path: .env
required: false
environment:
PORT: 4000

caddy:
image: caddy:2-alpine
depends_on:
- html2rss
- html2rss-web
command:
- caddy
- reverse-proxy
- --from
- ${CADDY_HOST}
- --to
- html2rss:3000
- html2rss-web:4000
ports:
- "80:80"
- "443:443"
Expand All @@ -23,14 +28,12 @@ services:
watchtower:
image: containrrr/watchtower
depends_on:
- html2rss
- html2rss-web
- caddy
command:
- --cleanup
- --interval
- "300"
- html2rss
- caddy
- "7200"
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
restart: unless-stopped
Expand Down
87 changes: 63 additions & 24 deletions src/components/docs/DockerComposeSnippet.astro
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
import Code from "astro/components/Code.astro";
import { Code } from "@astrojs/starlight/components";
import { browserlessImage, caddyImage, watchtowerImage, webImage } from "../../data/docker";

interface Props {
Expand All @@ -15,13 +15,19 @@ const snippets: Record<Props["variant"], string> = {
restart: unless-stopped
ports:
- "127.0.0.1:4000:4000"
env_file:
- path: .env
required: false
environment:
Comment thread
gildesmarais marked this conversation as resolved.
RACK_ENV: production
PORT: 4000
HTML2RSS_SECRET_KEY: your-generated-secret-key
HEALTH_CHECK_TOKEN: your-health-check-token
BUILD_TAG: \${BUILD_TAG:-local}
GIT_SHA: \${GIT_SHA:-local}
HTML2RSS_SECRET_KEY: \${HTML2RSS_SECRET_KEY:?set HTML2RSS_SECRET_KEY}
HEALTH_CHECK_TOKEN: \${HEALTH_CHECK_TOKEN:?set HEALTH_CHECK_TOKEN}
SENTRY_DSN: \${SENTRY_DSN:-}
BROWSERLESS_IO_WEBSOCKET_URL: ws://browserless:4002
BROWSERLESS_IO_API_TOKEN: your-browserless-token
BROWSERLESS_IO_API_TOKEN: \${BROWSERLESS_IO_API_TOKEN:?set BROWSERLESS_IO_API_TOKEN}
Comment thread
gildesmarais marked this conversation as resolved.

browserless:
image: "${browserlessImage}"
Expand All @@ -31,10 +37,11 @@ const snippets: Record<Props["variant"], string> = {
environment:
PORT: 4002
CONCURRENT: 10
TOKEN: your-browserless-token`,
TOKEN: \${BROWSERLESS_IO_API_TOKEN:?set BROWSERLESS_IO_API_TOKEN}`,
productionCaddy: `services:
caddy:
image: ${caddyImage}
restart: unless-stopped
ports:
- "80:80"
- "443:443"
Expand All @@ -46,39 +53,71 @@ const snippets: Record<Props["variant"], string> = {
- --from
- \${CADDY_HOST}
- --to
- html2rss:3000
html2rss:
- html2rss-web:4000

html2rss-web:
image: ${webImage}
env_file: .env
restart: unless-stopped
env_file:
- path: .env
required: false
environment:
RACK_ENV: production
PORT: 4000
BUILD_TAG: \${BUILD_TAG:-local}
GIT_SHA: \${GIT_SHA:-local}
HTML2RSS_SECRET_KEY: \${HTML2RSS_SECRET_KEY:?set HTML2RSS_SECRET_KEY}
HEALTH_CHECK_TOKEN: \${HEALTH_CHECK_TOKEN:?set HEALTH_CHECK_TOKEN}
SENTRY_DSN: \${SENTRY_DSN:-}
BROWSERLESS_IO_WEBSOCKET_URL: ws://browserless:4002
BROWSERLESS_IO_API_TOKEN: \${BROWSERLESS_IO_API_TOKEN:?set BROWSERLESS_IO_API_TOKEN}

browserless:
image: "${browserlessImage}"
restart: unless-stopped
environment:
PORT: 4002
CONCURRENT: 10
TOKEN: \${BROWSERLESS_IO_API_TOKEN:?set BROWSERLESS_IO_API_TOKEN}

volumes:
caddy_data:`,
secure: `services:
html2rss:
html2rss-web:
image: ${webImage}
restart: unless-stopped
env_file:
- path: .env
required: false
environment:
RACK_ENV: production
LOG_LEVEL: warn
HEALTH_CHECK_USERNAME: your-secure-username
HEALTH_CHECK_PASSWORD: your-very-secure-password
BASE_URL: https://yourdomain.com`,
PORT: 4000
BUILD_TAG: \${BUILD_TAG:-local}
GIT_SHA: \${GIT_SHA:-local}
HTML2RSS_SECRET_KEY: \${HTML2RSS_SECRET_KEY:?set HTML2RSS_SECRET_KEY}
HEALTH_CHECK_TOKEN: \${HEALTH_CHECK_TOKEN:?set HEALTH_CHECK_TOKEN}
SENTRY_DSN: \${SENTRY_DSN:-}
BROWSERLESS_IO_WEBSOCKET_URL: ws://browserless:4002
BROWSERLESS_IO_API_TOKEN: \${BROWSERLESS_IO_API_TOKEN:?set BROWSERLESS_IO_API_TOKEN}

browserless:
image: "${browserlessImage}"
restart: unless-stopped
environment:
PORT: 4002
CONCURRENT: 10
TOKEN: \${BROWSERLESS_IO_API_TOKEN:?set BROWSERLESS_IO_API_TOKEN}`,
watchtower: `services:
watchtower:
image: ${watchtowerImage}
depends_on:
- html2rss
- caddy
command:
- --cleanup
- --interval
- "300"
- html2rss
- caddy
restart: unless-stopped
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
restart: unless-stopped`,
# Optional for private registries only:
# - "\${HOME}/.docker/config.json:/config.json:ro"
command: --cleanup --interval 7200`,
resourceGuardrails: `services:
html2rss:
html2rss-web:
image: ${webImage}
deploy:
resources:
Expand Down
Loading
Loading