fredy README

The project's README from github.com/orangecoding/fredy. As one markdown file: README.md.

Fredy

Website  |   Demo  |   Quick Start  |   Docs

Tests Docker Source Docker Pulls

Fredy 🏡 - Your Self-Hosted Real Estate Finder for Europe

Fredy watches 26 real estate portals across 🇩🇪 🇦🇹 🇨🇭 🇪🇸 🇮🇹 🇵🇹 for you (e.g. Immoscout, Kleinanzeigen etc), drops duplicates across platforms, and notifies you via Slack, Telegram, Email, ntfy, Discord and more the moment a new listing appears. Searches are managed from a Web UI, and you never see the same listing twice.

On top of the listing itself, Fredy answers the three questions a portal will not:

orangecoding%2Ffredy | Trendshift

Fredy Maps View Dashboard Found Listings
Screenshot showing Fredy Screenshot showing job configuration in Fredy Screenshot showing found listings in Fredy

🚀 Quick Start

docker run -d --name fredy \
  -v fredy_conf:/conf \
  -v fredy_db:/db \
  -p 9998:9998 \
  ghcr.io/orangecoding/fredy:master

👉 Open http://localhost:9998 and sign in with admin / admin.

[!NOTE] No configuration file is needed to start. Fredy creates /conf/config.json on first run if it is missing. That file only holds the database path, everything else is configured in the Web UI and stored in the database. Documents you upload live in the database too, so the /db volume above is all you need to keep them, and every backup already contains them.

:master follows the master branch; pin a release with its version tag instead, e.g. ghcr.io/orangecoding/fredy:28.0.0. Images are built for linux/amd64 and linux/arm64. Logs: docker logs fredy -f.

There is also a pre-release channel following the develop branch, ghcr.io/orangecoding/fredy-pre-release:latest. It is built from the same pipeline (lint, format check and the offline test suite all have to pass first), but the changes in it have not been through master yet. Use it to try upcoming features or to verify a fix, not for an instance you rely on.

Node.js

Requires Node.js 22.22.0 or higher.

yarn
yarn run build:frontend  # builds the Web UI into ui/public
yarn run start:backend   # serves the UI and the API on port 9998

Unraid

Fredy is in the Unraid community store.


✨ What you get


🧩 Basic architecture overview

Concept What it is
Provider 🌐 A real-estate platform. You paste a search URL from the portal into Fredy, sorted by date.
Adapter 📡 A kind of connection Fredy can send through (Slack, Telegram, Email, ntfy, Discord ...). You never configure one on its own.
Channel 🔔 One filled-in adapter, e.g. "Telegram → family chat", saved once under Settings → Notification channels and reused in as many jobs as you like.
Job 📅 Providers + channels: "search ImmoScout24 and Immowelt, send to Slack and Telegram". Runs at the interval set under Administration → Execution.

A job can hold as many channels as you want, including several of the same type, and every new listing goes out through all of them at once. Rotating a token means editing one channel instead of every job that used it. Channels belong to whoever created them; an admin can share one with all users or with admins only, which lets others send through it without ever revealing its credentials. A channel still used by a job cannot be deleted.

flowchart TD

subgraph group_backend["Backend runtime"]
  node_entry["Server entry<br/>bootstrap<br/>[index.js]"]
  node_pipeline["Job pipeline<br/>orchestrator"]
  node_providers["Providers<br/>source integrations"]
  node_extractor["Extraction stack<br/>scraping services"]
  node_immoscout["ImmoScout path<br/>mobile-api translator"]
  node_notifications["Notifications<br/>delivery adapters"]
  node_storage[("SQLite storage<br/>persistence layer")]
  node_api["API routes<br/>http contract"]
  node_security["Security<br/>authz/authn<br/>[security.js]"]
  node_sse["SSE broker<br/>push channel<br/>[sse-broker.js]"]
  node_crons["Cron services<br/>background tasks"]
  node_geocoding["Geocoding<br/>location service"]
  node_listingqc["Listing QC<br/>dedupe/quality"]
end

subgraph group_frontend["Frontend app"]
  node_uientry["UI entry<br/>app bootstrap<br/>[Index.jsx]"]
  node_dashboard["Dashboard<br/>admin view<br/>[Dashboard.jsx]"]
  node_jobsui["Jobs UI<br/>admin view"]
  node_listingsui["Listings UI<br/>admin view"]
  node_adminui["Admin config<br/>admin view"]
end

subgraph group_ops["Operational surface"]
  node_debug["Debugging<br/>observability"]
  node_mcp["MCP server<br/>llm integration"]
end

node_entry -->|"serves"| node_api
node_entry -->|"starts"| node_pipeline
node_pipeline -->|"pulls listings"| node_providers
node_pipeline -->|"scrapes"| node_extractor
node_pipeline -->|"special case"| node_immoscout
node_pipeline -->|"dedupes"| node_listingqc
node_pipeline -->|"persists"| node_storage
node_pipeline -->|"fans out"| node_notifications
node_providers -->|"uses"| node_extractor
node_providers -->|"reads config"| node_storage
node_notifications -->|"reads state"| node_storage
node_api -->|"protects"| node_security
node_api -->|"reads/writes"| node_storage
node_api -->|"publishes"| node_sse
node_crons -->|"enriches"| node_geocoding
node_crons -->|"checks"| node_listingqc
node_crons -->|"updates"| node_storage
node_geocoding -->|"stores coords"| node_storage
node_debug -->|"captures logs"| node_storage
node_mcp -->|"queries"| node_storage
node_uientry -->|"consumes"| node_api
node_uientry -->|"subscribes"| node_sse
node_dashboard -->|"loads"| node_api
node_jobsui -->|"manages"| node_api
node_listingsui -->|"queries"| node_api
node_adminui -->|"configures"| node_api
node_adminui -->|"shows"| node_debug

click node_entry "https://github.com/orangecoding/fredy/blob/master/index.js"
click node_pipeline "https://github.com/orangecoding/fredy/blob/master/lib/FredyPipelineExecutioner.js"
click node_providers "https://github.com/orangecoding/fredy/tree/master/lib/provider"
click node_extractor "https://github.com/orangecoding/fredy/tree/master/lib/services/extractor"
click node_immoscout "https://github.com/orangecoding/fredy/tree/master/lib/services/immoscout"
click node_notifications "https://github.com/orangecoding/fredy/tree/master/lib/notification/adapter"
click node_storage "https://github.com/orangecoding/fredy/tree/master/lib/services/storage"
click node_api "https://github.com/orangecoding/fredy/tree/master/lib/api/routes"
click node_security "https://github.com/orangecoding/fredy/blob/master/lib/api/security.js"
click node_sse "https://github.com/orangecoding/fredy/blob/master/lib/services/sse/sse-broker.js"
click node_crons "https://github.com/orangecoding/fredy/tree/master/lib/services/crons"
click node_geocoding "https://github.com/orangecoding/fredy/tree/master/lib/services/geocoding"
click node_listingqc "https://github.com/orangecoding/fredy/tree/master/lib/services/listings"
click node_debug "https://github.com/orangecoding/fredy/tree/master/lib/services/debug"
click node_mcp "https://github.com/orangecoding/fredy/tree/master/lib/mcp"
click node_uientry "https://github.com/orangecoding/fredy/blob/master/ui/src/Index.jsx"
click node_dashboard "https://github.com/orangecoding/fredy/blob/master/ui/src/views/dashboard/Dashboard.jsx"
click node_jobsui "https://github.com/orangecoding/fredy/tree/master/ui/src/views/jobs"
click node_listingsui "https://github.com/orangecoding/fredy/tree/master/ui/src/views/listings"
click node_adminui "https://github.com/orangecoding/fredy/tree/master/ui/src/views"

classDef toneNeutral fill:#f8fafc,stroke:#334155,stroke-width:1.5px,color:#0f172a
classDef toneBlue fill:#dbeafe,stroke:#2563eb,stroke-width:1.5px,color:#172554
classDef toneAmber fill:#fef3c7,stroke:#d97706,stroke-width:1.5px,color:#78350f
classDef toneMint fill:#dcfce7,stroke:#16a34a,stroke-width:1.5px,color:#14532d
classDef toneRose fill:#ffe4e6,stroke:#e11d48,stroke-width:1.5px,color:#881337
classDef toneIndigo fill:#e0e7ff,stroke:#4f46e5,stroke-width:1.5px,color:#312e81
classDef toneTeal fill:#ccfbf1,stroke:#0f766e,stroke-width:1.5px,color:#134e4a
class node_entry,node_pipeline,node_providers,node_extractor,node_immoscout,node_notifications,node_storage,node_api,node_security,node_sse,node_crons,node_geocoding,node_listingqc toneBlue
class node_uientry,node_dashboard,node_jobsui,node_listingsui,node_adminui toneAmber
class node_debug,node_mcp toneMint

📚 Going deeper

Topic What is in there
Providers & scraping All 26 providers, the Immoscout / idealista / Casa.it specifics, and residential proxies for when a VPS gets blocked
Scam detection The signals, their weights, the languages, and how to overrule Fredy
Financing calculator Rent and Annuitätendarlehen, Kaufnebenkosten, Restschuld, the 35 % rule
Travel time & public transport Addresses and place types, estimated vs exact, route drawing, departure boards, operator settings
MCP server Connecting Claude, ChatGPT or a local LLM to your listings
Reverse proxy sign-in Forward auth with Authelia, Authentik, oauth2-proxy, Traefik, Pangolin
Debug bundles Capturing logs for a bug report
Development Dev mode, tests, fixtures, adding a language
Contributing Writing a provider or a notification adapter

🤖 MCP Server

Since V20, Fredy ships a built-in MCP Server, so you can connect it to Claude, ChatGPT or a local model (LM Studio) and query your real estate data in natural language. A local LLM can even enrich existing listings by checking them online. Setup: MCP Readme.

To connect Claude.ai or ChatGPT over OAuth, set Fredy's baseUrl to its public HTTPS URL and add <baseUrl>/api/mcp as a custom MCP server. Fredy advertises OAuth discovery metadata, dynamically registers the client, and asks you to sign in and approve read access. Access tokens expire after one hour and refresh automatically; existing MCP tokens keep working for local clients. Connected apps are listed under Settings → Connections, where access can be revoked at any time.


📊 Analytics

Fredy is completely free (and will always remain free). However, it would be a huge help if you would allow me to collect some analytical data. Before you freak out, let me explain: if you agree, Fredy sends a ping every 6 hours to my internal tracking project (will be open sourced soon). The data includes which notification adapters and providers are in use (the type only, for example slack, never your channels, their names or their credentials), OS, architecture, Node version and language. It is entirely anonymous and helps me understand which adapters and providers matter most.

Thanks 🤘


🤝 Sponsorship

I build and maintain Fredy in my free time. If it saves you some, consider chipping in ❤️

Support me on Ko-fi Sponsor on GitHub

Fredy is backed by the JetBrains Open Source Support Program.

JetBrains Open Source Support Program

👐 Contributing

Thanks to everyone who has contributed!

Start with the Contributing Guide; it also covers where AI-assisted contributions help, and where they do not.


🗺️ Data Attribution & Partners

Timetables, journey planning and travel times come from Transitous, a community-run MOTIS instance. It is free, needs no API key, and is maintained by volunteers, so please be considerate with the load you put on it and read their usage policy before pointing a large instance at it. Street and map data come from OpenStreetMap contributors.

Every listing with coordinates links out to Lagecheck, which rates the address on noise, air quality, green space and flood risk. Fredy only builds the link and stores nothing from it; the underlying data is by geosci.de.

Transitous

📄 License

Apache-2.0 with two additional conditions:

Because of these conditions Fredy is source-available, not OSI open source. Read the full LICENSE before building anything commercial on top of it.


💬 Support


⭐ Star History

Fredy star history

fredy (orangecoding/fredy)

Searching Database…

1.6K ·GitHub
这是什么?Fredy 是一个自托管工具,持续盯着德国、奥地利、瑞士、西班牙、意大利和葡萄牙的 26 个房产门户网站(如 ImmoScout24、Immowelt、eBay Kleinanzeigen),新房源一出现就立刻通过 Slack、Telegram、邮件、Discord 或 ntfy 推送给你。
它是浏览器扩展,还是要自己托管的东西?它是一个用 Docker 或 Node.js 运行的自托管 Web 应用;搜索、渠道和任务都在 Fredy 自己的 Web UI 里配置,而不是浏览器插件。
怎么让它跑起来?推荐用 Docker:拉取并运行 ghcr.io/orangecoding/fredy 镜像,无需任何设置,因为首次运行时会创建 /conf/config.json。它也可以直接用 Node.js 跑,或从 Unraid 社区商店安装。
除了 Docker 还需要什么?如果不用 Docker、直接运行,需要 Node.js 22.22.0 或更高版本;走 Docker 路线没有任何额外前置要求。
诈骗检测能抓住每条假房源吗?不能,它只在一条房源上凑够足够多租房诈骗信号时才发出警示,而且永远应该以你自己的判断优先于 Fredy 的结论。
Fredy 会把我的数据发回给开发者吗?只在你主动选择加入时:之后它每 6 小时向一个内部分析项目发送匿名数据,比如你启用了哪些通知适配器和数据源、你的操作系统和 Node 版本——绝不会发渠道名称或凭据。
我能出售基于 Fredy 搭建的服务吗?不能。许可证是 Apache-2.0 加 Commons Clause 条款,禁止出售该软件或任何价值主要来自它的产品,另外还有一条针对衍生作品的署名条款——自己免费自托管明确没问题,但它是源码可见(source-available),不是 OSI 开源。
Fredy 的 MCP 服务器能让我做什么?它让 Claude、ChatGPT 或本地 LLM 能用自然语言查询你保存的房源,本地 LLM 甚至可以上网核查来充实已有的房源信息。
跨门户的去重是怎么做的?Fredy 按居住面积、房间数和位置来匹配房源,而不是按标题,所以同一套房同时发在 ImmoScout、Immowelt 和 Kleinanzeigen 上时,你只会收到一次。
Fredy 怎么计算到房源的路程时间?它通过 Transitous 行程规划器使用从你的地址出发的公共交通、开车、骑车和步行的真实路线,而不是直线距离,还能在地图上显示实时发车信息。
贷款计算器核算什么?你只需输入一次收入、生活开支和储蓄,每条房源都会据此在租房和买房两方面衡量,包括 35% 准则这类规则和购房附加成本(Kaufnebenkosten)。
Size
45.9 MB
Stars
1.6K
Age
8y
Commits · 90 Days