# Threema Web: a self-hostable encrypted messenger client that is in maintenance mode

> Threema Web is the browser client for the Swiss encrypted messenger, pairing with a phone over WebRTC or encrypted WebSockets with SaltyRTC signalling, and it is now in maintenance mode while the developers work on a desktop replacement.

**threema-ch/threema-web** — The Threema Web application.

- Repository: https://github.com/threema-ch/threema-web
- Stars: 1,069 · Forks: 108
- Language: TypeScript
- License: AGPL-3.0
- Published: 2026-10-19 · Updated: 2026-10-19 · Language: en
- Canonical page: https://hysenlabs.com/projects/threema-ch-threema-web

## What the client does, and how the phone and desktop talk

Threema Web is a web client for Threema, a privacy-focussed end-to-end encrypted mobile messenger hosted and developed in Switzerland. The project's framing is that with Threema Web you can use Threema on your desktop without compromising security, and the hosted instance runs at web.threema.com.

The connection model is the interesting technical part. Threema Web establishes a connection between the desktop and the mobile device using WebRTC on Android, or encrypted WebSockets on iOS. And the signalling and the data are end-to-end encrypted with SaltyRTC, which is the reason the WebSocket path can be encrypted too: a raw WebSocket would be no better than a plain connection, so the protocol layer on top of it is what preserves the end-to-end property.

The details of the cryptography are in the Threema Cryptography Whitepaper, and the protocol used to communicate between the Threema app and Threema Web is documented separately in the app-remote-protocol repository, which is a reasonable split: the wire protocol is a contract between two independently released artefacts, the mobile app and this client.

The primary language of the repository is TypeScript, the licence is AGPL-3.0 with a LICENSE.txt at the root, and there is a separate LICENSE-3RD-PARTY.txt for the third party library licences, with a gather-licenses.sh script in the tree to regenerate it. The last push was on 2026-10-12 and the releases are v2.6.5 from 2026-07-03, v2.6.4 from 2026-03-09 and v2.6.3 from 2025-12-13.

## Maintenance mode, and what that means for a deployment

The first thing in the README is a warning, and it is the single most important fact for anyone considering this project.

Threema Web is in maintenance mode while the developers are working on Threema for Desktop 2.0, which should resolve some of the long-standing issues they were having with Threema Web. They will still do regular maintenance and fix critical bugs, but for now there will be no major new features or non-critical bugfixes, with the pull request at github.com/threema-ch/threema-web/pull/996 given for details.

So the project is not abandoned, it is frozen in feature terms. The distinction matters for a self-hosted deployment: you will not get new capabilities, and you will not get the long-standing issues fixed by a patch, because the fix is expected to arrive in a different artefact.

Two smaller points follow from the same posture. There is a beta testing channel, where experimental branches are occasionally deployed to web-beta.threema.com and testers are encouraged to try them, with the expectation that problems are reported along with the experiment's version number, for example 1.2.3-experiment-beta4. So there is still active experimentation, it just is not landing in the main line.

And the version numbering continues to move, with the releases above, which is consistent with a project that still ships maintenance fixes.

For an adopter, the practical question is whether you want the web client specifically. If you want a desktop client for Threema, the developers have told you where the effort is going. If you specifically need a self-hostable browser client, this remains the only one, and it remains AGPL licensed and self-hostable.

## Building it, and the Node version that decides whether you can

The development setup is short and the toolchain is dated in a way you need to plan for.

Threema Web is written using TypeScript and AngularJS 1, with dependencies managed by npm, and you currently need Node.js 24 to build it. The README notes that Node.js is only a build dependency, since the result is plain old client-side JavaScript, which is a good property for a self-hosted deployment because the runtime does not need Node at all.

If your default Node version is not 24, the README suggests nvm:

```
    nvm install
    nvm use
```

Then the development dependencies and the dev server:

```
    npm install
```

```
    npm run devserver
```

And you open the URL in your browser:

```
    firefox http://localhost:9966
```

The devserver script in the manifest shows how that works, running the CSS build first and then starting a CSS watcher and a webpack dev server together with concurrently under the kill-others and names css,server options. The note in the README is that this setup should not be used in production, and to run Threema Web on a server you should follow the instructions at docs/self_hosting.md.

The build itself is split in two. The build script runs build:js and build:css, where the JavaScript is webpack with webpack.prod.js and the CSS is sass with the deprecation warning for import silenced, outputting compressed stylesheets from src/sass/ into public/css/. There are separate webpack configs for the common case, the dev server, production and the test bundle, which is webpack.common.js, webpack.dev.js, webpack.prod.js and webpack.tests.js.

The dist script is the packaging step: it cleans, builds, and runs node dist/build-package.js. That is what the Docker build uses to produce the release artefact.

## Tests, linting, and the two-tier test setup

The test setup has three layers, and the split is visible in the scripts.

Unit tests run with karma, and the manifest shows the test script runs the unit test bundle build and then karma with single-run, debug log level and colors. The unit test bundle is built with webpack.tests.js, and karma.conf.js at the root is the karma configuration.

UI tests run a shell script, tests/ui/run.sh, and the documentation gives the sequence:

```
    npm run build  # Required for CSS to be rebuilt
    npm run test:ui <browser>
```

With examples for firefox and chrome, and the ability to filter the test cases by passing a further argument:

```
    npm run test:ui firefox emoji
```

That CSS rebuild requirement is worth noting, because the UI tests render real pages and the stylesheet is not built by the test bundle, so a stale public/css/ produces failures that have nothing to do with the code under test.

Linting is tslint, not eslint, run against the tsconfig project with src/config.ts excluded, which is excluded because that file is generated or templated. The README also shows how to install a pre-push hook that runs the linting, written directly into .git/hooks/pre-push with a shell script and made executable.

The repository has a .devcontainer directory for a reproducible development environment, .tx for translation management, a CHANGELOG.md, a RELEASING.md, a CVEs.md, a TRANSLATING.md, and a troubleshoot directory.

## Configuration, the container, and the TLS gap you have to close

Configuration is split by when it is read, and the split is deliberate.

The configuration of Threema Web can be tweaked in src/config.ts and in src/userconfig.js and src/userconfig.overrides.js, with an example file at src/userconfig.overrides.js.example. The config variables are defined at build time, and the userconfig variables can be modified at runtime. The userconfig.overrides.js.example file is the documented template for the runtime overrides.

In the Docker image, all userconfig variables can be overridden using environment variables, with the details in docs/docker.md. That is what makes the container usable in an orchestrated deployment where you do not want to bake settings into an image.

The Dockerfile is where the deployment constraints show. It is a two-stage build: the first stage is docker.io/node:24 with NODE_ENV=production, which runs a sed over src/config.ts to set SELF_HOSTED to true, then npm ci and npm run dist with the d argument. The second stage is docker.io/nginx:1.27-alpine, which installs bash, clears the default html directory and copies the release output into it along with an entrypoint script. It hides the nginx version with a server_tokens off config, exposes port 80, sets VISUALIZE_STATE and CONSOLE_LOG_LEVEL, and runs the entrypoint through bash.

The warning at the top of the Dockerfile is the thing to read twice: this Dockerfile does not include TLS termination, and you must run the container behind a reverse proxy that does proper TLS termination. For a messenger client whose entire value is the encryption claim, running it over plain HTTP behind a proxy that does not terminate TLS would undermine the point, and the project says so rather than leaving you to work it out.

The runtime configuration surface is also where the self-hosting decision becomes concrete, since the SELF_HOSTED flag is what the Docker build turns on, and it is the flag that tells the client it is not talking to the public service.

## Conclusion

Threema Web fits an organisation that wants to run the encrypted messenger's desktop client inside its own network boundary, or a user who wants a client they can host rather than one at web.threema.com. It is a poor fit if you need new features, because the project is explicitly in maintenance mode with no major new features or non-critical fixes planned, and it is a poor fit if you want a modern framework, since it is built on AngularJS 1. Before adopting, read the self-hosting instructions, put a reverse proxy with real TLS termination in front of the container because the image does not terminate TLS itself, and check the signing key expiry listed in the README.

## FAQ

### What is Threema Web and how does it connect to a phone?

It is the web client for Threema, a privacy-focussed end-to-end encrypted mobile messenger hosted and developed in Switzerland. It establishes a connection between the desktop and the mobile device using WebRTC on Android or encrypted WebSockets on iOS, and the signalling and data are end-to-end encrypted with SaltyRTC.

### Is Threema Web still being developed?

It is in maintenance mode. The developers are working on Threema for Desktop 2.0, which should resolve some of the long-standing issues with Threema Web. They will still do regular maintenance and fix critical bugs, but there will be no major new features or non-critical bugfixes for now.

### What do I need to build Threema Web?

Node.js 24, npm for dependencies, TypeScript and AngularJS 1 as the stack. The README suggests using nvm if your default Node version is not 24, then npm install and npm run devserver, after which you open http://localhost:9966 in the browser. That dev setup is explicitly not for production; use docs/self_hosting.md for a real deployment.

### How do I run the Threema Web tests?

Unit tests run with karma after building the unit test bundle, and UI tests run with npm run test:ui <browser>, for example firefox or chrome, with an extra argument to filter the cases. The UI test run requires a CSS rebuild first, since npm run build is needed for the stylesheet to be current.

### Can I run Threema Web in Docker with TLS?

The image is built from node:24 and served by nginx:1.27-alpine, but the Dockerfile states that it does not include TLS termination, so you must run the container behind a reverse proxy that terminates TLS properly. All userconfig variables can be overridden with environment variables in the image.

## Sources

- [Issues](https://github.com/threema-ch/threema-web/issues)
- [License: AGPL-3.0](https://github.com/threema-ch/threema-web/blob/master/LICENSE)
- [README](https://github.com/threema-ch/threema-web/blob/master/README.md)
- [Releases](https://github.com/threema-ch/threema-web/releases)
- [threema-ch/threema-web on GitHub](https://github.com/threema-ch/threema-web)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/threema-ch-threema-web
