Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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:
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}

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 html2rss-web browserless caddy`,
resourceGuardrails: `services:
html2rss:
html2rss-web:
image: ${webImage}
deploy:
resources:
Expand Down
Loading
Loading