This is the only hand-written project document in docs/.
Keep this file short, current, and operational. Do not add planning docs, migration diaries, redesign notes, or parallel architecture narratives back into this directory.
The only generated artifact intentionally exposed by the app is public/openapi.yaml.
- Backend: Ruby + Roda under the
Html2rss::Webnamespace. - Frontend: Preact + Vite, built into
frontend/distand served at/. - Feed extraction: delegated to the
html2rssgem. - Distribution: Docker Compose / Dev Container first.
- Runtime behavior: application code plus tests.
- HTTP contract: request specs plus generated OpenAPI.
- This file: contributor conventions and current project rules only.
Primary local gate:
docker compose -f .devcontainer/docker-compose.yml exec -T app make ready
Useful commands:
docker compose -f .devcontainer/docker-compose.yml exec -T app make setup
docker compose -f .devcontainer/docker-compose.yml exec -T app make dev
docker compose -f .devcontainer/docker-compose.yml exec -T app bundle exec rspec
docker compose -f .devcontainer/docker-compose.yml exec -T app make openapi
docker compose -f .devcontainer/docker-compose.yml exec -T app make openapi-verify
docker compose -f .devcontainer/docker-compose.yml exec -T app make openapi-lint
Frontend verification lives at http://127.0.0.1:4001/ while the dev container is running.
app/is the Zeitwerk root forHtml2rss.app/web/**maps directly toHtml2rss::Web::*.- Match constant, filename, and directory exactly.
- Keep route composition in
app/web/routes/**. - Keep
/api/v1contract-specific code inapp/web/api/**. - Keep feed fetching, caching, and orchestration in
app/web/feeds/**. - Keep auth, token handling, URL validation, and security logging in
app/web/security/**. - Keep request-scoped context in
app/web/request/**. - Keep boot/runtime setup in
app/web/boot/**. - Do not create generic buckets such as
services,helpers,utils, orconcerns.
public/openapi.yamlis generated output, not hand-edited design prose.- Backend behavior and request specs define the contract.
- Regenerate with
make openapi. - Drift must fail with
make openapi-verify. - Quality must fail with
make openapi-lint. - Frontend generated client code under
frontend/src/api/generatedis machine-generated only.
Managed flags:
| Name | Env key | Type | Default |
|---|---|---|---|
auto_source_enabled |
AUTO_SOURCE_ENABLED |
boolean | true in development/test, else false |
async_feed_refresh_enabled |
ASYNC_FEED_REFRESH_ENABLED |
boolean | false |
async_feed_refresh_stale_factor |
ASYNC_FEED_REFRESH_STALE_FACTOR |
integer >= 1 |
3 |
Rules:
- Invalid managed flag values must fail fast at boot.
- Unknown managed feature-style env keys must fail fast at boot.
- Add or change flags in code, tests, and this table together.
Canonical event fields:
event_nameschema_versionrequest_idroute_groupactoroutcome
Optional request context fields:
pathmethodstrategystarted_atdetails
Critical-path event families:
- auth
- feed create
- feed render
- request errors
- Prefer deleting stale docs over archiving them in-place.
- If a rule matters to contributors, keep it here.
- If a detail is generated from code, keep it out of prose docs.
- If a design idea is temporary, keep it in the PR or issue, not under
docs/.