Skip to content

About

A minimal feedreader

Resources

Stars

2 stars

Watchers

1 watching

Forks

Repository files navigation

feedreader

A Gleam/Erlang RSS and Atom feed reader. Tracks feeds, fetches entries on a schedule, and serves a server-rendered HTML UI with HTMX for partial updates.

Features

  • Subscribe to RSS/Atom feeds (manual add or OPML import)
  • Unread, starred, and history views
  • Ever-opened tracking for entry content and comments links (first open only)
  • Background scheduler fetches new entries every 3 minutes
  • SQLite storage via sqlight + Parrot codegen
  • Server-rendered HTML with Lustre + lustre_pipes + HTMX
  • No authentication (handle at the reverse proxy / network layer)

Quick start

mise install          # install gleam, erlang, rebar3
gleam deps download
gleam run             # serves on http://localhost:3000

The database defaults to feedreader.db in the working directory. Override with the DATABASE_PATH environment variable.

Content and comments links have independent first-open timestamps (content_opened_at and comments_opened_at). JavaScript records keyboard, regular-click, Cmd/Ctrl-click, and middle-click activations in the background; later opens do not change the timestamps. Opening a link does not mark the entry as read, and changing read status does not erase these timestamps. Existing entries start with no recorded opens when the database is upgraded.

Tracking is best-effort if the background request fails. Context-menu “open link” actions are not tracked.

Development

gleam check           # type check
gleam test            # run the test suite
gleam format          # format code
mise run pre-commit   # format + check + lint + test
mise run gen          # regenerate Parrot SQL codegen from schema + queries
mise run assets       # install + build TailwindCSS

Run the browser event-handler tests separately with Node.js:

mise exec node@24.20.0 -- node --test test/feedreader/web/entry-opens.test.js

Deploy with Docker

The CI builds a multi-arch image (amd64 + arm64) and pushes it to GHCR on every push to main and on version tags (v1.0.0).

docker pull ghcr.io/kasuboski/feedreader:main
docker run -d \
  -p 3000:3000 \
  -v feedreader-data:/data \
  -e DATABASE_PATH=/data/feedreader.db \
  ghcr.io/kasuboski/feedreader:main

Or with docker-compose (see docker-compose.yaml):

docker compose up -d

The SQLite database persists in a Docker volume mounted at /data. To migrate from the old Elixir/Phoenix deployment, copy the existing feedreader.db into the volume — the schema is compatible.

Architecture

Layer Technology
Language Gleam → Erlang/BEAM
Web server Wisp + Mist
HTML rendering Lustre SSR + lustre_pipes
Interactivity HTMX via hx
Database SQLite via sqlight + Parrot
Background workers Gleam/OTP actors (scheduler + fetcher) under a supervisor

See SCOUTING_REPORT.md for the full Elixir → Gleam migration analysis.

About

A minimal feedreader

Resources

Stars

2 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages