Open source-byggblock
Att bygga hela ingestionsmotorn från grunden är onödigt — flera mogna open source-projekt löser stora delar av problemet. Här är en djupare titt på fynden. Allt nedan kan köras på Hetzner-värden och anpassas till hur många källor som helst.
Tre arkitektoniska riktningar
Innan vi går igenom enskilda verktyg: tre kompletta arkitekturer som täcker hela behovet. De skiljer sig i hur mycket vi köper färdigt mot bygger själva.
┌──────────────────────────────────────────────────────────────┐ │ RSS-källor → Miniflux (Docker) │ │ ├── jo, imy, ad, av… └─ REST API ─┐ │ │ └── eeln, hrw, nvc… │ │ │ ▼ │ │ Anti-bot HTML → changedetection.io (Docker) │ │ └── amnesty, coe, fra… └─ webhook ──┐ │ │ │ │ │ Special API:er → egna Python-fetchers │ │ ├── HUDOC (ECtHR) │ │ │ ├── CELLAR SPARQL (CJEU) │ │ │ └── UHRI dump (FN-organ) │ │ │ ▼ │ │ Email-bridge → IMAP-skript │ │ └── isf, mfd, riksrev… │ │ │ ▼ │ │ Panorama events-DB (SQLite) │ │ │ │ │ ┌──────────────────────┴───────┐ │ │ ▼ ▼ │ │ Flask UI Datasette │ │ (jurist + admin) (data.tritagonist.se) │ └──────────────────────────────────────────────────────────────┘
┌──────────────────────────────────────────────────────────────┐ │ │ │ Activepieces (eller n8n) │ │ ┌──────────────────────────────┐ │ │ │ RSS-flow → HTML-flow │ │ │ │ ↓ ↓ │ │ │ │ Normalize → Dedup │ │ │ │ ↓ │ │ │ │ HTTP POST → Panorama DB │ │ │ └──────────────────────────────┘ │ │ │ │ │ ▼ │ │ Panorama events-DB │ │ │ │ │ ┌────────┴────────┐ │ │ ▼ ▼ │ │ Flask UI Datasette │ └──────────────────────────────────────────────────────────────┘
┌──────────────────────────────────────────────────────────────┐ │ │ │ Prefect (eller apscheduler) │ │ ┌────────────────────────────────────────────────┐ │ │ │ Per källa: hämtfunktion + Pydantic-modell │ │ │ │ ┌─────────┬──────────┬──────────┬──────────┐ │ │ │ │ │ rss.py │ html.py │ api.py │ browser │ │ │ │ │ └─────────┴──────────┴──────────┴──────────┘ │ │ │ │ Retries · backoff · dead-letter │ │ │ └────────────────────────────────────────────────┘ │ │ │ │ │ ▼ │ │ Normalizer (Event-modell, deduplikering) │ │ │ │ │ ▼ │ │ Panorama events-DB (SQLite) │ │ │ │ │ ┌────────┴────────┐ │ │ ▼ ▼ │ │ Flask UI Datasette │ └──────────────────────────────────────────────────────────────┘
Bedömning per komponent
Minimalistisk self-hosted RSS-läsare med fullständigt REST-API och Fever-API. Skriven i Go, en statisk binär, körs gärna i Docker. Hanterar etag/last-modified, parallell polling, deduplikering, läs-status och full text-search ur lådan. Stöder per-feed filter-regler (regex på title/description) och custom user-agent.
Naturlig botten för RSS-skiktet. Värt att starta här.
Featurerik konkurrent till Miniflux. Stort extension-ekosystem, inkluderar moduler för att generera feeds från sajter som saknar dem (XPath-baserad scraping). Stöder Google Reader-API och har multi-user-stöd om det skulle behövas.
Bra om XPath-extensions kan ersätta 5–10 av HTML-scrape-källorna. Annars är Miniflux enklare.
"Berätta för mig när den här sidan ändras." CSS/XPath-selektorer per URL, visual diff, optional Playwright-container för JS-tunga sajter. Webhook-out vid förändring. Specifikt utformad för att kringgå anti-bot-skydd via headless browser-rendering.
Den enskilt bästa lösningen på anti-bot-problemet. Värt sin minnesförbrukning.
Visuell workflow-byggare med 400+ noder, AI-integrationer, vector stores. Drag-and-drop-flöden där varje nod är ett steg (HTTP, Cron, Transform, IF-then…). Den polerade lösningen för no-code-användare som vill äga sina flows.
Tekniskt kapabel, men licensen gör det olämpligt för en myndighetsdriven prototyp.
Yngre n8n-konkurrent med riktig open source-licens. Visuell workflow-byggare, "pieces" istället för "nodes" (~200 färdiga). Aktivt utvecklat 2025–2026, har vunnit mark från n8n efter dess licensändring.
Den bästa visuella plattformen för det här ändamålet om vi vill ha drag-and-drop. Annars är hybrid-vägen lättare.
Den klassiska "agent-baserade" web-monitoringsplattformen. Varje agent är en konfigurerbar enhet som lyssnar efter händelser, hämtar data eller utlöser åtgärder. Kombinera dem i kedjor. Mycket flexibelt för exakt det vi behöver.
Hade varit förstavalet 2017. Idag finns färskare alternativ.
Modern workflow-orkestrerare. Inga rigida DAG:s — vanlig Python-kod med @flow/@task-dekorerare. Schemaläggning, retries, observability, parallellism. Tänk Airflow utan komplexitet.
Rätt val om vi gör clean-slate-vägen. För hybriden räcker apscheduler eller cron.
Det de facto-mogna Python-ramverket för web-scraping. Scrapy är biblioteket, Scrapyd är scheduler-daemonen, ScrapydWeb/Gerapy är web-UI:n ovanpå. Tillsammans en komplett pipeline för spiders med statistik, loggar, scheduling.
Bättre att använda changedetection.io för enkla "ny publikation"-detekteringar och bara dra in Scrapy om vi har källor där vi behöver djup HTML-parsning.
Plugin-baserat scraping-bibliotek som täcker alla federala domstolar och de flesta delstatsdomstolar i USA. Backboner för CourtListener. Arkitekturen — en scraper-modul per domstol med gemensamt interface — är värd att studera för vår design.
Inte direkt användbart, men kodbasen är referensläsning för "hur man bygger en plugin-driven domstols-scraper".
Forskningsprojekt från Poznan University of Technology som har laddat ner, normaliserat och taxonomerat hela HUDOC. Resultatet är en versionerad open dataset med metadata-features, klar för machine learning eller direkt databasimport.
Ladda in dumpen en gång som baslinje. Polla HUDOC backend-API för deltadata.
Web-UI för utforskande analys av SQLite-databaser. Vi kör redan en instans på data.tritagonist.se. Stöder facets, sökning, JSON-export, ärftliga vyer, plugin-ekosystem.
Behåll och utöka. När events-tabellen växer kommer Datasette vara guld.
Typo-toleranta sökmotorer som indexerar dokument och returnerar relevanta träffar i millisekunder. Båda har enkla REST-API:er och kräver minimal konfiguration. Typesense har bättre fasetterad sökning, Meilisearch har snyggare default-relevans.
Vänta tills vi har volym. SQLite full-text search räcker länge.
Snabb översikt — sortera per kategori
| Verktyg | Kategori | Licens | Stack | Hetzner-vänlig | Passform |
|---|---|---|---|---|---|
| Miniflux | RSS-aggregator | MIT | Go + Postgres | Ja, 10 MB | Hög |
| FreshRSS | RSS-aggregator | AGPL-3.0 | PHP + SQLite | Ja, 50 MB | Hög |
| Tiny Tiny RSS | RSS-aggregator | GPL-3.0 | PHP + Postgres | Ja | Låg (maintainerproblem) |
| changedetection.io | Web-monitor | Apache-2.0 | Python + Playwright | Ja, 150 MB+ | Hög |
| urlwatch | CLI-monitor | BSD | Python | Ja, ingen tjänst | Medel |
| Scrapy + Scrapyd | Scraping-framework | BSD | Python | Ja, 300 MB | Medel |
| Juriscraper | Legal scraping (USA) | BSD | Python | Ja | Låg (USA) |
| n8n | Visual workflow | Sustainable Use | Node.js + Postgres | Ja, 500 MB | Låg (licens) |
| Activepieces | Visual workflow | MIT | TypeScript + Postgres | Ja, 400 MB | Hög |
| Huginn | Agent-based | MIT | Ruby on Rails + MySQL | Ja, 250 MB | Medel |
| Node-RED | Visual workflow | Apache-2.0 | Node.js | Ja, 100 MB | Medel |
| Prefect | Workflow-orchestrator | Apache-2.0 | Python | Ja, 200 MB | Hög (clean-slate) |
| Dagster | Data-orchestrator | Apache-2.0 | Python | Ja, 400 MB | Medel (för komplext) |
| Apache Airflow | Workflow-orchestrator | Apache-2.0 | Python + Postgres | Ja, 800 MB | Låg (overkill) |
| apscheduler | Scheduler-bibliotek | MIT | Python (in-process) | Ja, ~0 MB | Hög (för enkelt) |
| Datasette | Data-explorer | Apache-2.0 | Python + SQLite | Ja, redan i stack | Hög |
| Meilisearch | Sökmotor | MIT | Rust | Ja, 100 MB | Medel (senare) |
| Typesense | Sökmotor | GPL-3.0 | C++ | Ja, 80 MB | Medel (senare) |
| ECHR-OD | Dataset | CC-BY-4.0 | — | Ja, statiska filer | Hög |
Vad händer när vi lägger till fler källor
Källkatalogen kommer att växa. Bedömningen av hur olika arkitekturer skalar:
Miniflux klarar 1000+ feeds utan konfigändring. changedetection.io skalar genom att lägga till watchers via UI eller dess API. De egna special-fetcherna är CPU-bundna men källspecifika — fler källor ger inte fler API:er att lära sig.
Varje ny källa = ett nytt workflow. UI:t kan hantera hundratals flows, men efter en viss volym blir det rörigt utan tagging/foldering. Workflow-databasen kan växa snabbt och behöver underhåll.
För varje ny källa behövs YAML-entry + ev. ny fetcher-kod + deploy. Smidigt vid 50 källor, friktion vid 200. Lägg till "ny källa via UI" som krav i den arkitekturen om vi går den vägen.
Konkret första steg
Sätt upp en Miniflux-container på Hetzner-värden bredvid de befintliga Panorama-containrarna. Lägg in de 13 verifierade RSS-feedarna manuellt. Polla Miniflux REST-API från Flask en gång per timme och persistera nya items till en events-tabell i SQLite. Det ger oss:
Inget av besluten är låsta — Miniflux REST-API är standard nog att vi kan byta ut det senare utan att röra resten av stacken.