Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
f46ccfa
feat: astro frontend
gildesmarais Sep 9, 2025
e7cf89f
integrate astro
gildesmarais Sep 9, 2025
dbb68c5
auto reload
gildesmarais Sep 9, 2025
2bf5773
feat: enhance development experience with live reload and new Ruby se…
gildesmarais Sep 14, 2025
92a065b
feat: enhance auto source functionality with authentication and usage…
gildesmarais Sep 14, 2025
0d4965c
refactor: remove outdated test scripts and clean up package dependencies
gildesmarais Sep 15, 2025
edf4072
autosource views in astro
gildesmarais Sep 18, 2025
870327c
clean roda app
gildesmarais Sep 18, 2025
cae7703
unify make lint & ~fix
gildesmarais Sep 18, 2025
632b40f
fix ctrl+c make dev
gildesmarais Sep 18, 2025
47b982b
make lintfix
gildesmarais Sep 18, 2025
6ba5790
integrate astro-starlight
gildesmarais Sep 18, 2025
270bdb7
add api to return available request strategies
gildesmarais Sep 18, 2025
7162569
slim frontend, add ux-friendly autosource auth using hmac + docs
gildesmarais Sep 18, 2025
d031291
improve auto_source ux
gildesmarais Sep 18, 2025
80d6726
style and ux
gildesmarais Sep 18, 2025
caa892d
refactor: roda app structure / routes
gildesmarais Sep 19, 2025
3bfa3ac
tool-versions it is
gildesmarais Sep 19, 2025
85683fb
ruby clean
gildesmarais Sep 19, 2025
08b3d4d
refactor: enhance routing and response handling; improve frontend vis…
gildesmarais Sep 19, 2025
3dec638
simplecov coverage
gildesmarais Sep 19, 2025
7f7a39e
csp + error
gildesmarais Sep 19, 2025
02ac635
rack attack
gildesmarais Sep 20, 2025
df5600b
log for rack-attack
gildesmarais Sep 20, 2025
35a5798
roda structure
gildesmarais Sep 20, 2025
175d504
clean unreloader setup
gildesmarais Sep 20, 2025
cd47adf
preact
gildesmarais Sep 23, 2025
1bb7df4
api/v1, legacy clean, token in url path and zlib'ed
gildesmarais Sep 24, 2025
d6123a3
Remove obsolete specs for Html2rss::Web components including AutoSour…
gildesmarais Sep 25, 2025
886c754
Refactor auto source configuration and improve request handling
gildesmarais Sep 25, 2025
f003084
unify ci workflows
gildesmarais Sep 26, 2025
4061876
docs
gildesmarais Sep 27, 2025
405eec5
css
gildesmarais Sep 27, 2025
d7c24e6
ask api/v1/strategies
gildesmarais Sep 27, 2025
170dac4
Remove rack-attack middleware
gildesmarais Jan 25, 2026
ed109c5
Bind feed strategy in tokens
gildesmarais Jan 25, 2026
44b7866
Surface UI auth and preview errors
gildesmarais Jan 25, 2026
4b2b917
Tighten README
gildesmarais Jan 25, 2026
c510adb
ci: fix double runs
gildesmarais Jan 25, 2026
805eb31
style: prettier
gildesmarais Jan 25, 2026
50d2f7f
Document devcontainer workflow
gildesmarais Jan 25, 2026
34ead2c
Add make ready pre-commit gate
gildesmarais Jan 25, 2026
d13773c
Refactor spec doubles for Html2rss feeds
gildesmarais Jan 25, 2026
cc3c9d4
Fix devcontainer up workflow
gildesmarais Jan 25, 2026
524edd3
Align dev ports to 4000-range
gildesmarais Jan 25, 2026
0c2f47e
Clarify agent collaboration rules
gildesmarais Jan 25, 2026
60eb9d2
Fix legacy feed lookup and cache TTL
gildesmarais Jan 25, 2026
34d9ef2
style: agents relax
gildesmarais Jan 25, 2026
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
34 changes: 34 additions & 0 deletions .devcontainer/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
FROM ruby:3.4.6-alpine3.21

SHELL ["/bin/sh", "-o", "pipefail", "-c"]

RUN apk add --no-cache \
bash \
build-base \
curl \
git \
libxml2-dev \
libxslt-dev \
nodejs \
npm \
openssl-dev \
python3 \
tzdata

ARG USER=vscode
ARG UID=1000
ARG GID=1000

RUN addgroup -g "$GID" "$USER" \
&& adduser -D -G "$USER" -u "$UID" "$USER"

WORKDIR /workspace
RUN chown -R "$USER":"$USER" /workspace

ENV BUNDLE_PATH=/usr/local/bundle

USER "$USER"

EXPOSE 4000

CMD ["sleep", "infinity"]
49 changes: 49 additions & 0 deletions .devcontainer/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# Dev Container Workflow

This repository ships a single Dev Container for development. Open the project in VS Code (Dev
Containers extension) or GitHub Codespaces and use that environment for all work.

## What gets created

The devcontainer starts one service named `app` and exposes:

- **Port 4000:** Ruby app
- **Port 4001:** Astro dev server

The repo is mounted at `/workspace`. Bundler gems are cached in a Docker volume to speed up
future launches.

## Bootstrap

On first open, the Dev Container runs:

```
make setup
```

This installs Ruby and frontend dependencies inside the container.

If setup fails due to missing network access (e.g., GitHub DNS), rerun `make setup` once
network access is available.

## Common commands (run inside the container)

```
make dev # Ruby + Astro
make dev-ruby # Ruby only
make dev-frontend # Astro only
make test # Ruby + frontend tests
make ready # RuboCop + RSpec (pre-commit gate)
```

## Lint and tests

```
bundle exec rubocop -F
bundle exec rspec
```

## Notes

- All commands are expected to run inside the Dev Container.
- The default service command is `sleep infinity`; use the Make targets above to start servers.
50 changes: 26 additions & 24 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
@@ -1,41 +1,43 @@
{
"name": "html2rss-web",
"image": "mcr.microsoft.com/devcontainers/ruby:3.4",
"features": {
"ghcr.io/devcontainers/features/git:1": {},
"ghcr.io/devcontainers/features/github-cli:1": {}
},
"dockerComposeFile": "docker-compose.yml",
"service": "app",
"workspaceFolder": "/workspace",
"shutdownAction": "stopCompose",
"customizations": {
"vscode": {
"extensions": [
"redhat.vscode-yaml",
"esbenp.prettier-vscode",
"github.copilot",
"github.copilot-chat",
"shopify.ruby-lsp"
"rebornix.ruby",
"astro-build.astro-vscode",
"esbenp.prettier-vscode"
],
"settings": {
"ruby.rubocop.executePath": "bundle exec",
"ruby.format": "rubocop",
"ruby.lint": {
"rubocop": true
},
"editor.formatOnSave": true,
"editor.defaultFormatter": "esbenp.prettier-vscode",
"files.associations": {
"*.erb": "erb"
}
"*.astro": "astro"
},
"prettier.configPath": "./frontend/.prettierrc",
"ruby.format": "rubocop",
"ruby.lint": { "rubocop": true },
"editor.tabSize": 2,
"editor.insertSpaces": true,
"files.trimTrailingWhitespace": true,
"files.insertFinalNewline": true
}
}
},
"postCreateCommand": "make setup",
"postStartCommand": "echo '🚀 html2rss-web Development Environment Ready!' && echo '' && echo '📋 Quick Start Commands:' && echo ' make dev # Start development server' && echo ' make test # Run tests' && echo ' make lint # Run linter' && echo ' make fix # Auto-fix linting issues' && echo ' make help # Show all commands' && echo '' && echo '🌐 Server will be available at: http://localhost:3000' && echo '📁 Project files are in: /workspaces/html2rss-web' && echo '' && echo '💡 Tip: Use Ctrl+C to stop the development server' && echo ''",
"forwardPorts": [
3000
],
"forwardPorts": [4000, 4001],
"portsAttributes": {
"3000": {
"label": "html2rss-web",
"4000": {
"label": "Ruby App",
"onAutoForward": "notify"
},
"4001": {
"label": "Astro Dev Server",
"onAutoForward": "silent"
}
},
"postCreateCommand": "bash -lc \"make setup || (echo 'make setup failed; rerun once network access is available.' && exit 0)\"",
"remoteUser": "vscode"
}
20 changes: 20 additions & 0 deletions .devcontainer/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
services:
app:
build:
context: ..
dockerfile: .devcontainer/Dockerfile
volumes:
- ../:/workspace:cached
- bundle-cache:/usr/local/bundle
ports:
- "4000:4000"
environment:
- RACK_ENV=development
- BUNDLE_PATH=/usr/local/bundle
- PORT=4000
command: sleep infinity
user: vscode
working_dir: /workspace

volumes:
bundle-cache:
71 changes: 49 additions & 22 deletions .github/copilot-instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,36 +3,57 @@
## Overview

- Ruby web app that converts websites into RSS 2.0 feeds.
- Built with **Roda**, using the **html2rss** gem (+ `html2rss-configs`).
- **Principle:** _All features must work without JavaScript._ JS is only progressive enhancement.
- Built with **Roda** backend + **Astro** frontend, using the **html2rss** gem (+ `html2rss-configs`).
- **Frontend:** Modern Astro-based UI with component architecture, served alongside Ruby backend.

## Documentation website of core dependencies

Search these pages before using them. Find examples, plugins, UI components, and configuration options.

### Roda

1. https://roda.jeremyevans.net/documentation.html

### Astro & Starlight

1. https://docs.astro.build/en/getting-started/
2. https://starlight.astro.build/getting-started/

### html2rss

1. If available, find source locally in: `../html2rss`.
2. source code on github: https://github.com/html2rss/html2rss

### Test and Linters

1. https://docs.rubocop.org/rubocop/cops.html
2. https://docs.rubocop.org/rubocop-rspec/cops_rspec.html
3. https://rspec.info/features/3-13/rspec-expectations/built-in-matchers/
4. https://www.betterspecs.org/

Fix rubocop `RSpec/MultipleExpectations` adding rspec tag `:aggregate_failures`.

## Core Rules

- ✅ Use **Roda routing with `hash_branch`**. Keep routes small.
- ✅ Put logic into `helpers/` or `app/`, not inline in routes.
- ✅ Organise Roda routes via dedicated modules (e.g. `Html2rss::Web::Routes::*`), keeping the main app class thin.
- ✅ Keep helper modules minimal: define entrypoints with `class << self` and push implementation helpers under `private`; avoid `module_function` unless mirroring existing conventions.
- ✅ Validate all inputs. Pass outbound requests through **SSRF filter**.
- ✅ Add caching headers where appropriate (`Rack::Cache`).
- ✅ Errors: friendly messages for users, detailed logging internally.
- ✅ CSS: Water.css + small overrides in `public/styles.css`.
- ✅ Specs: RSpec, unit + integration, use VCR for external requests.

## Don’t
- ✅ **Frontend**: Use Astro components in `frontend/src/`. Keep it simple.
- ✅ **CSS**: Use frontend styles provided by Astro Starlight.
- ✅ **Specs**: RSpec for Ruby, build tests for frontend.
- ✅ When a spec needs to tweak environment variables, wrap the example in `ClimateControl.modify` so state is restored automatically.

- ❌ Don’t depend on JS for core flows.
- ❌ Don’t bypass SSRF filter or weaken CSP.
- ❌ Don’t add databases, ORMs, or background jobs.
- ❌ Don’t leak stack traces or secrets in responses.
## Don't

## Project Structure

- `app.rb` – main Roda app
- `app/` – core modules (config, cache, ssrf, health)
- `routes/` – route handlers (`hash_branch`)
- `helpers/` – pure helper modules (`module_function`)
- `views/` – ERB templates
- `public/` – static assets (CSS/JS, minimal)
- `config/feeds.yml` – feed definitions
- `spec/` – RSpec tests + VCR cassettes
- ❌ Don't use Ruby's URI class or addressable gem directly. Strictly use `Html2rss::Url` only.
- ❌ Don't bypass SSRF filter or weaken CSP.
- ❌ Don't add databases, ORMs, or background jobs.
- ❌ Don't leak stack traces or secrets in responses.
- ❌ Don't reach into private API with `send(...)`; expose what you need at the module level instead.
- ❌ Don't modify `frontend/dist/` - it's generated by build process.
- ❌ NEVER expose the auth token a user provides.

## Environment

Expand All @@ -41,6 +62,12 @@
- `HEALTH_CHECK_USERNAME`, `HEALTH_CHECK_PASSWORD`
- `SENTRY_DSN` (optional)

### Verification Steps

- Run `ruby -c app.rb` to check syntax
- Run `bundle exec rspec` to verify tests
- Check `bundle install` removes unused dependencies

## Style

- Add `# frozen_string_literal: true`
Expand Down
17 changes: 0 additions & 17 deletions .github/workflows/bundle-update.yml

This file was deleted.

Loading
Loading