This repository is part of the source code of Wire. You can find more information at wire.com or by contacting opensource@wire.com.
You can find the published source code at github.com/wireapp/wire.
For licensing information, see the attached LICENSE file and the list of third-party licenses at wire.com/legal/licenses/.
If you compile the open source software that we make available from time to time to develop your own mobile, desktop, or web application, and cause that application to connect to our servers for any purposes, we refer to that resulting application as an "Open Source App". All Open Source Apps are subject to, and may only be used and/or commercialized in accordance with, the Terms of Use applicable to Wire Application, which can be found at https://wire.com/legal/#terms. Additionally, if you choose to build an Open Source App, certain restrictions apply, as follows:
a. You agree not to change the way the Open Source App connects and interacts with our servers; b. You agree not to weaken any of the security features of the Open Source App; c. You agree not to use our servers to store data for purposes other than the intended and original functionality of the Open Source App; d. You acknowledge that you are solely responsible for any and all updates to your Open Source App.
For clarity, if you compile the open source software that we make available from time to time to develop your own mobile, desktop, or web application, and do not cause that application to connect to our servers for any purposes, then that application will not be deemed an Open Source App and the foregoing will not apply to that application.
No license is granted to the Wire trademark and its associated logos, all of which will continue to be owned exclusively by Wire Swiss GmbH. Any use of the Wire trademark and/or its associated logos is expressly prohibited without the express prior written consent of Wire Swiss GmbH.
apps/webapp/: React client (Rspack internal, public production, and development), plus E2E tests and i18n filesapps/server/: node/express wrapper that serves the built webapp and handles proxyingapps/server/configuration/: configuration generators, environment contracts, and browser-safe build metadata functionsapps/webapp/src/script/core/: communication core handling authentication, WebSocket connections, protocol messaging, and shared storage engines- Root-level tooling (
justfileandtools/) provides commands for both applications. Webapp dependencies live in the rootpackage.jsonandpackage-lock.json;apps/serverremains an npm workspace for build and development dependencies. Production artifacts run without installed npm packages.
The browser keeps Ky 1.x as ky; release tooling imports its existing Ky 2.x dependency as ky-release because its HTTP error handling uses error.data. Unifying those versions requires a separate compatibility migration. Commander remains on the root tooling's 15.x version; the former webapp 14.x declaration had no application or tooling imports.
Use npx just --list to discover repository tasks, including builds, development, type checks, unit tests, linting, E2E, and translation management.
Prerequisites:
- Install Node.js
- Use Node.js 26.12.1, as pinned by
.nvmrc. - Use npm 11.20.0, bundled with Node.js 26.12.1 and declared by the root
package.jsonpackageManagerfield. - The
devEngineschecks require Node.js>=26.12.1 <27and npm>=11.20.0 <12fornpm installandnpm clean-install.
- Run
npm clean-installto install dependencies from the committed root lockfile. - Run
npx just setupto apply dependency patches, fetch the webapp configuration, generate React icons, and validate their types.configure-webappusesapps/webapp/app-config/package.jsonto select a config repository version (wire-web-config-wireorwire-web-config-default), then copies:- config content into
apps/webapp/resource/ .env.defaultsinto repository root
- config content into
- Runtime priority is: process environment (for example AWS) >
.env>.env.defaults> code fallback.
- Copy
.env.localhostto.envto override/extend defaults - Add the following entries to your hosts file (macOS / Linux:
/etc/hosts, Windows 10:%WINDIR%\system32\drivers\etc\hosts):127.0.0.1 local.zinfra.io(to connect with the staging backend)127.0.0.1 local.imai.wire.link(to connect with the imai backend)
- Run
npx just develop; Just builds the server output, then starts the Express server and its TypeScript watcher. Rspack compiles the WebApp in memory and serves it at https://local.zinfra.io:8081/auth/ with React Fast Refresh. - Server TypeScript changes are recompiled with
tsc --watch;node --watchrestarts the compiled Express server when its output changes.concurrentlystops sibling processes if any watcher exits. - In case you're facing a CORS issue after login when the app tries to fetch
self/consentfrom the backend, appendFEATURE_CHECK_CONSENT="false"to the env file
If you would like your browser to trust the certificate from "local.wire.com"/"local.zinfra.io"/"local.imai.wire.link":
- Download mkcert - Installation on Mac:
brew install mkcert(refer to the latest README.md) - Set the
CAROOTenvironment variable to<WebApp Dir>/apps/server/certificate - Run
mkcert -install
The application can be configured to connect to different environments by modifying the following environment variables in your .env file:
For the full environment variable reference, see Environment Variables.
Staging:
APP_BASE="https://local.zinfra.io:8081"
BACKEND_REST="https://staging-nginz-https.zinfra.io"
BACKEND_WS="wss://staging-nginz-ssl.zinfra.io"
Imai:
APP_BASE="https://local.imai.wire.link:8081"
BACKEND_REST="https://nginz-https.imai.wire.link"
BACKEND_WS="https://nginz-ssl.imai.wire.link"
Local:
APP_BASE="http://localhost:8081"
BACKEND_REST="http://localhost:8080"
BACKEND_WS="ws://localhost:8080"
After updating the environment variables, the app will be available at the corresponding APP_BASE URL.
Build a one-shot development-mode WebApp bundle with npx just build-webapp-development. The static files are written to apps/webapp/dist/development. This does not start the live development server: use npx just develop for the server with Rspack watch mode and hot reload.
Rspack is the sole application bundler for internal and public production builds and local development. Jest continues to use Babel.
- Build only the internal Rspack WebApp assets:
npx just build-webapp-internal - Type-check and bundle the production server with its runtime assets:
npx just build-server-bundle(writes toapps/server/build/bundle) - Build and package the default internal Rspack release:
npx just package-server-internal- This builds both the server and webapp (in production mode) and creates the deployment package at
apps/server/dist/s3/ebs.zip
- This builds both the server and webapp (in production mode) and creates the deployment package at
- Build and package the default public Rspack release:
npx just package-server-public - Start the server output from
apps/server/dist(or build a Docker image withnpx just docker <tag>)
Both packaging tasks reuse the minified Rspack server bundle and assemble it with the selected browser build into apps/server/dist. The artifact includes the server source map, GeoIP database, templates, certificates, robots, telemetry embed, environment defaults, and shared version metadata. The server source map stays alongside index.js, outside the HTTP static directories. Docker and Elastic Beanstalk launch Node with --enable-source-maps and install no npm packages. Local development continues to use TypeScript compilation and installed workspace dependencies.
Telemetry's TypeScript implementation lives in apps/webapp/src/script/telemetry. The server copies the unmodified countly-sdk-web/lib/countly.min.js build dependency directly to libs/wire/telemetry/embed.js. Both HTML templates load this standalone SDK before the application bundles; telemetry initializes only when explicitly requested by the application.
Note: The zip command has been deprecated. Packaging is integrated into the build process via npx just package-server-internal.
Configuration tests live alongside the generators and metadata functions in apps/server/configuration/ and run with the server Jest project. Run npx just test --selectProjects server to check them. After packaging, npx just verify-server-package extracts the ZIP outside the repository with no installed packages and checks startup, /version, /config.js, template rendering with GeoIP, private source maps, and mapped exception stacks. npx just verify-server-bundle also checks Rspack statistics for minification and unexpected external dependencies.
Run all unit tests:
npx just testRun npx just test-ci to execute each Jest project with coverage and its existing project-specific thresholds. CI uses this command inside the network-isolation wrapper and uploads HTML and LCOV reports for the webapp, server, core, and API client. Use npx just test-watch for watch mode.
Core tests retain a separate Node Jest project in apps/webapp/test/core/jest.config.js, with minimum coverage of 49% branches, 53% functions, and 62% lines/statements. Run it directly with npx jest --config apps/webapp/test/core/jest.config.js --coverage. Its original discovery patterns still exclude encryptedStore.test.node.ts. Webapp tests and coverage exclude the core tree; explicit service fixtures remain in src/script/util/test/createCoreTestFixture.ts.
API-client source lives in apps/webapp/src/script/apiClient/ and is compiled and watched directly by Rspack. Import individual source modules using relative paths. Browser adapters are passed at the webapp construction boundaries; Node tests pass the Node adapters explicitly. Its separate Node Jest project is apps/webapp/test/apiClient/jest.config.js: run npx jest --config apps/webapp/test/apiClient/jest.config.js --coverage. Webapp test discovery and coverage exclude this tree, and core coverage excludes it too. Coverage thresholds remain 50% branches, 40% functions, and 53% lines/statements. tsconfig.api-client.json preserves the source's stricter checks without emitting a separate library build. APIClient.VERSION retains the final standalone SDK version, 27.96.0, independently of the webapp release version.
UI-kit components live in apps/webapp/src/script/uiKit/ and are compiled and watched directly by Rspack. Import individual source modules using relative paths. Their behavior tests retain a separate jsdom/SWC Jest project in apps/webapp/test/uiKit/jest.config.js. Run it with npx jest --config apps/webapp/test/uiKit/jest.config.js --coverage; just test-ci also runs it. Webapp test discovery and coverage exclude this tree to avoid counting it twice. The Emotion theme augmentation lives beside the components in emotion.d.ts and is included by the webapp TypeScript configurations.
Asset encryption uses the browser crypto implementation explicitly. Node asset tests pass the Node implementation through the existing asset functions and AssetService constructor. Core source changes are compiled and watched directly by Rspack, without a separate library build or watcher.
Other useful tasks:
- Lint:
npx just lint - ESLint only:
npx just eslint - Fix ESLint issues:
npx just eslint --fix - Type-check:
npx just type-check - E2E (Playwright):
npx just e2e-test(for example,npx just e2e-test --grep "@regression|@crit-flow-web") - E2E UI mode:
npx just e2e-ui
All Wire translations are crowdsourced via Crowdin.
Install dependencies with npm clean-install and run npx just setup. Create a Crowdin personal access token, then set it in your shell:
export CROWDIN_PERSONAL_TOKEN="<personal-access-token>"The committed crowdin.yaml is the CLI configuration. It keeps the Crowdin project ID and translation paths; authentication comes from CROWDIN_PERSONAL_TOKEN. Do not add credentials to the configuration file.
Use these Just recipes from the repository root:
npx just translate-extractscans i18next strings in webapp JavaScript, HTML, and template files.npx just translate-mergeextracts FormatJS strings and merges them intoapps/webapp/src/i18n/en-US.jsonusing the custom formatter.npx just translate-validatechecks translation file structure and placeholder markers against the canonical English file.npx just translate-uploadruns both source extraction steps and explicitly uploads source strings only. It does not upload translated locale files.npx just translate-downloadexplicitly downloads translated locale files and validates their placeholders.
Uploads and downloads are opt-in local actions. After an English source change is reviewed and merged to main, the push workflow prepares the canonical source strings and uses the pinned Crowdin GitHub Action to upload sources. The manually dispatched pull workflow downloads translations, validates placeholders, and opens the existing translation pull request. These workflows remain separate from the local Just commands.
Contributions are welcome! Feel free to check our issues page.
The following commits will help you get started quickly with our code base:
