A forum, chat rooms, voice rooms and events in one self hosted app.
Run it locally ·
Conventions ·
Web app ·
MIT license
Most communities are split across a chat app, a forum, a call link and a calendar. Good answers get lost in the scroll. Hearth puts it all in one place and keeps what matters as posts. A chat thread can become a post, and a post talked through live in a voice room keeps the recording and transcript, so people find it again later.
You run it yourself, so your members' data lives on servers you choose. Transcripts and screening run on your own machines by default, and nothing goes to an outside AI service unless you turn one on. Photos and videos have their location and camera details removed before anyone else can see them.
A two minute look at Hearth in use. Click the picture to play it.
![]() |
![]() |
![]() |
![]() |
Forum with questions, answers, tags, boosts and photo galleries. Catch up shows what's new across your communities, with email digests
Chat rooms, replies, mentions, boosts and direct messages, all live. A good thread can become a post
Voice rooms that are open to everyone or run with a stage, with screen share, recordings and transcripts. A recording takes the name of the event on in the room, and whoever recorded it can rename or delete it. Transcripts and live captions only appear when the instance sets
TRANSCRIPTION=local, and run on your own serverEvents with reminders
Roles and invites for each community, by link or by email
Moderation with reports, a review queue, bans and a public log. Optional screening holds risky posts for a person to decide, and never removes anything itself
Sign in with an email code, or with Google and GitHub when set up
Installable as an app, with push notifications
Easy to find with sitemaps for search engines and a share card drawn for every link
You need PostgreSQL, Node and ffmpeg, which converts videos and recordings.
With asdf or mise installed, make setup installs the Elixir and Erlang
versions in .tool-versions for you. make install-deps installs only the
dependencies, without touching the database.
make setup # dependencies, database and git hooks
cp .env.example .env # Google, GitHub, JWT and push keys, if you want them
make dev # the API on :4000 and the web app on :5174The first account to sign up runs the instance. After that, make seed adds
sample communities for trying moderation, owned by the account named in
SEED_OWNER.
make dev.api and make dev.web start one at a time. Ctrl+C stops both. make help lists every target.
To try the app with sample data and no server, run VITE_HEARTH_DATA=mock pnpm dev in web.
Public screens render on the server, so search engines and link previews get
the content. For a production build run pnpm build and then pnpm start,
with PUBLIC_URL set to the site's address and API_INTERNAL_URL to the API's.
Run make test for every test in both apps, make format to format both, make lint for Credo and oxlint, and make check before you push. It runs formatting, compiler warnings, Credo, Sobelow, the Elixir tests and the web app's own check. make coverage writes a coverage report for the Elixir apps and fails under the minimum in coveralls.json. make clean removes build output and keeps dependencies.
After changing an endpoint, run make gen.api. It writes the API's OpenAPI file
again and regenerates the web app's client from it.
To watch the API while you work, make observe starts Grafana with
Prometheus, Tempo and Loki at http://localhost:3000. Then make dev.api.observe
runs the API with its metrics, traces and logs going there.
docs/CONVENTIONS.md describes how the code is laid out.
Docker runs the whole stack behind Caddy, which gets a certificate for your
domain. Fill in .env with at least PUBLIC_URL, PUBLIC_HOST,
POSTGRES_PASSWORD, SECRET_KEY_BASE, JWT_PRIVATE_KEY and the mail
settings, then start it.
make up # Postgres, the API, the web app and Caddy
make up.dev # the same, with Mailpit catching email on :8025
make down # stops it and keeps the dataThe files are in infra/. To also start coturn, which relays voice for people
behind strict networks, run
docker compose --env-file .env -f infra/compose.yml --profile voice up -d.
A Helm chart in infra/k8s/hearth runs the API in pools by role (web, media,
ai and voice) with the web server beside them. HEARTH_ROLES decides what
each pod starts, so a media pod only processes files and an ai pod only
screens. Secrets come from HashiCorp Vault, which the API reads itself at
boot. There's a values file per environment.
make k8s.lint # checks the chart, offline
make k8s.render ENV=production # prints the manifests
make k8s.apply ENV=staging # installs or upgrades in the current contextinfra/k8s/README.md covers setting up Vault, voice networking and the
optional in-cluster Postgres and object storage.
Instance settings tells admins when a new version is out. Back up the database
and keep your .env, then pull the new version and restart Hearth the way you
installed it. With Docker, git pull and make up run the migrations before
the new version starts. On Kubernetes, make k8s.apply does the same. From a
release, run bin/migrate before bin/server.
Elixir and
Phoenix, with Oban,
PostgreSQL and S3 compatible storage
React and
Vite, with
Tailwind CSS and an API client generated by orval





