vielhuber / extrablatt
A simple news aggregator in php.
Requires
- php: >=8.3
- ext-gd: *
- ext-pdo_sqlite: *
- vielhuber/aihelper: ^5.0.0
Requires (Dev)
None
Suggests
None
Provides
None
Conflicts
None
Replaces
None
This package is auto-updated.
Last update: 2026-09-06 05:33:54 UTC
README
📰 extrablatt 📰
a simple news aggregator in politically charged times. pulls articles from configurable rss feeds (plus reddit, hacker news and x via cookie-authenticated scrape), stores them in sqlite, detects paywalls, fetches thumbnails, categorises through an llm, and opens single articles through an archive.ph proxy with mobile-friendly css rewrites. installable as a progressive web app.
installation
mkdir extrablatt
cd extrablatt
composer require vielhuber/extrablatt
./vendor/bin/extrablatt-init
after install, edit:
.data/config.json: papers (see schema below).data/.env:AI_API_KEY/AI_BASE_URL/AUTH_PASSWORD/AI_PROVIDER/AI_MODEL.data/cookies/: drop cookie exports per host into.data/database.sqlite: restore database (optional)
config.json schema
{
"papers": {
"<paper-key>": {
"url": "https://example.com",
"label": "Display Name",
"rss": "https://example.com/feed.xml",
"default_image": "https://example.com/fallback.png",
"stub_markers": ["Subscribe to read", "Premium content"]
}
}
}
default_image(optional): fallback thumbnail when the RSS item carries no image.stub_markers(optional): substrings present in the archive.ph snapshot of a PLUS article when it's only a teaser, so the snapshot is dropped instead of surfaced as if it were the full text.following(optional,medium://homeonly): explicit list of followed handles (@username) and publication slugs whose RSS feeds get aggregated. Without it the list is discovered from the cookie-authenticated/followingpage, which Cloudflare challenges from datacenter IPs — so shared hosting needs this key.- Special
rssschemes:reddit://home,x://homeandhackernews://bestactivate the dedicated scrapers in place of XML parsing;medium://homeaggregates the followed authors' RSS feeds;ct://archivindexes the complete c't article archive (needs no login, backfills a bounded number of issues per scrape, rating = editorial page count).
the Gesundheit tab stores manual weight, body-fat percentage, blood-pressure, and pulse measurements in SQLite and reads the Google Health API (daily rollups of the paired watch). set GOOGLE_HEALTH_CLIENT_ID / GOOGLE_HEALTH_CLIENT_SECRET in .env, register the site root as the OAuth redirect URI, publish the cloud project (publishing status Testing makes google revoke the refresh token every 7 days), then visit /?health=connect once.
the Crypto tab shows rolling one-year and four-week BTC/EUR and ETH/EUR price histories from CoinGecko's public endpoint without a configured API key, using the bundled Chart.js library and compact widgets for both periods. market data stays fresh for 15 minutes, with the last cached response retained through temporary API failures; the weekly digest describes the most recent four weeks above the weather without duplicating the charts.
the Lokal tab after BILD shows PNP articles from the publisher's Lokales and Bayern sections, with optional topic filters. During each digest scrape, these same sections supply a separate Lokales & Regionales prose block for the past seven days, including read articles. Existing cached digests gain the block on the next successful scrape; without matching articles or an AI response, it is omitted.
categories, AI defaults (temperature, timeout, max_tries), and the archive fulltext minimum (8000 chars) are hardcoded in the package.
usage
php -S 127.0.0.1:8080 -t .
cron
0 6,18 * * * curl -s 'https://your-host/?scrape=1&key=<AUTH_PASSWORD>' >/dev/null
deployment
production consumes this repository as the Composer package vielhuber/extrablatt.
- Test the task branch, update the package version with
npm version <version> --no-git-tag-version, and commit the release changes. - Merge the tested branch into
main, create the matching version tag on the merged commit, and pushmainand that tag. The tag is published through Packagist. - On production, back up
composer.jsonandcomposer.lockoutside the public document root or in a protected dot directory. - Preview the targeted update with
composer update vielhuber/extrablatt:<version> --dry-run --no-dev --prefer-dist --no-interaction. Only the Extrablatt package should change. - Run the same command without
--dry-run. Keep the application's configuration, cookies and SQLite database untouched. - Run the existing authenticated scrape and check its completion and the regenerated weekly digest. Verify that the installed package reference matches the release tag.
For a package rollback, restore the saved Composer files and run composer install --no-dev --prefer-dist --no-interaction. This restores package versions, not data changed by a scrape.
backup
zip -r backup.zip .data