> Most of my contacts made the switch, and I’m now at roughly 95% Signal for day-to-day conversations
Years ago, I set up a Matrix server. I got some people to migrate, but ultimately even my husband stopped using it because the UI and accessibility of all the applications was so poor (and he has very bad eyesight, so this was a dealbreaker)
Looking for another alternative, I ended up with Telegram. It was pretty open, easy to work with, had great UI and even a ton of funny stickers and emojis, so I got nearly all my friends to migrate. I did NOT go for Signal because I do not need end-to-end encryption all the time, and having all the same conversations available on my desktop as well as on my phone was important, and still is. Unfortunately, it's also run by a severe weirdo.
So yeah, I'm not really sure what to use now.
Telegram is almost on the opposite end of the spectrum of Matrix & Signal so I wouldn’t really consider it an alternative.
Their text explicitly acknowledges and waives away the security concerns for themselves.
How so? I genuinely don't know, despite casually using both.
Opposite end in terms of security. Telegram group chats have no E2EE, private messages aren't E2EE by default (you have to initiate it as a "secret" chat), and the encryption itself is home rolled.
Yup exactly, their home rolled encryption is problematic in and of itself, but the fact that it lacks E2EE means you shouldn’t even trust it in the first place.
It also contains scam advertisement by now.
It,s quite clear what you never used it. UX wise it's one of the best clients and probably in the top 3 network-wise.
It's deeply insecure in most of the ways it is used.
But people don't care about security, that is obvious, they only care about UX
I should have been clearer in my initial post, but I was referring to the security issues with telegram rather than the UI.
Over the years there's been a couple of apps that have tried to use email protocols as the backend for chat. I really wish those had gained popularity - there's a lot of overlap with messaging and email.
Isn't that just email then? I mean I guess you could wrap a bubbly UI around it, but you're not getting around the latency and spam. Those seem like dealbreakers to me.
DeltaChat supposedly does that but I've never tried to interoperate it with email
Deltachat moved away from email, to their own protocol called chatmail
On the Matrix accessibility side, Element X has improved loads over the years - https://element.io/blog/helping-to-get-everyone-in-their-ele... and https://element.io/blog/element-is-accessible-by-design/ etc.
Recently came across FluffyChat (https://fluffy.chat/), which works on matrix and has funny stickers and emojis ;)
I've been using fluffychat for over a year. It's a nice interface and the client I used to convince less technical friends and family to give Matrix a try. Unfortunately major functionality like being able to send images becomes broken for long periods of time https://github.com/krille-chan/fluffychat/issues/2497
And for desktop apps, Cinny has custom emoji/sticker support. Would be nice if they played better with Element though.
Signal supports desktop clients now, no?
How are you framing this? It’s an Electron app so it exists but doesn’t integrate or perform great. Last I recall you still were required to provide a SIM to sign up & you needed an iOS or Android primary device to even use the desktop client. Can you use a standalone, fast desktop application like you can these other protocols? I would say no, so “support” has shades of gray to it.
This is how I got kicked off LINE… they had a Chromium app that I could use tethered to an app, they disabled support for LINE Lite (which had light/dark theme, E2EE, texting, voice/video calls, debatable trackers (Firebase), even stickers & sending a location @ 8MiB instead of 200MiB+ of the “heavy app”), I refused to “upgrade” as it was a downgrade to me, & since I was no longer registered with a “primary” device, I was booted from the network. I don’t think I want these mobile-duopoly-required apps to be my primary means of communication with folks—especially now that my primary phone isn’t Apple or Google (luckily Open Whisper lets WhisperFish exist).
> but doesn’t integrate or perform great.
Curious what you mean by this. I use the Signal Desktop app. It does what it's supposed to - send and receive messages in a timely way with no lag.
What poor performance are you seeing? What doesn't integrate?
Not GP but I've also had issues with the Signal Desktop app (installed from the Arch repos).
Its overall a little sluggish in general (like most Electron apps though, in fairness) and occasionally clicking and dragging images onto the application will cause it to freeze and eventually crash.
Plus, the general usability issues present in all variants of the signal client (like no easy way of restoring previous messages on a new device).
It's not terrible or anything, but it's just a solid 6/10 application. I personally wish they were more open to 3rd party clients, so I could have something that integrates with my desktop environment a little better and is snappier, like my Matrix clients.
The Signal desktop app works fine, but you are right, it is still tied to a mobile account and a phone number. This is the main downside to Signal. I read that the Molly fork will support multiple accounts and a self hostable server. It probably won't be federated, but that is not really a problem when you can use multiple accounts and avoids a lot of headaches that come with federation.
Has done for years now, but its desktop support is far inferior to even Matrix chat clients. It works in a pinch but you have to lower your standards quite a lot to use it as a true alternative.
> Unfortunately, it's also run by a severe weirdo.
Marlinspike, Acton, or someone else? Why does this matter?
I think they're talking about Telegram for that part.
Snikket ( https://snikket.org/ ) is an easier way to self-host an XMPP server. It's a pre-configured Prosody server in a docker image, and you can use it with any XMPP client you like.
> I still use Signal for most day-to-day conversations and I’m not planning to stop.
You can run a Signal-XMPP gateway. See https://slidge.im/
This will allow you to use your Signal account from your XMPP client. Bridging audio / video calls isn't currently possible. But most other feature work across the gateway.
> Snikket
I once looked into that and it just confuses me, it’s XMPP but requires an invite? And the snikket client only works with snikket servers, yet it’s actually all based on prosody and conversations? Everything about the project has alarms going off for me.
You're supposed to self-host it (or rent a hosted instance). But rather than having open registration (or creating accounts beforehand and sending the credentials), you generate invites and send them to your contacts. The invites onboard the users to install the app.
The Snikket client works with any XMPP server, and the Snikket server works with any XMPP client.
The Snikket clients are soft forks of existing clients. The reason of their existence is having consistent branding.
In fact, I recommend using Monal as an iOS client instead of the Snikket iOS one.
Note: you can set up invites on any regular Prosody / ejabberd server.
https://prosody.im/doc/modules/mod_invites
https://docs.ejabberd.im/admin/configuration/modules/#mod_in...
I'm the founder of both the Prosody and Snikket projects. Sorry about triggering alarms :) I can try to explain...
Prosody is a popular choice of XMPP server software. It's used for all kinds of stuff, from self-hosted chat servers to powering Jitsi Meet, to Internet-of-Things applications.
Prosody is extremely flexible, and has a bunch of configuration options that allow you to adapt it and extend it however you want. For some people, this is ideal. Those people should continue using Prosody.
Snikket has a different scope. It is specifically an answer to a question like "How can I easily make a self-hosted WhatsApp/Signal for my family/friends using open-source software?"
- Snikket contains Prosody, for the core chat part. But it's Prosody with a very specific configuration, and the configuration is part of the project, it's not intended to be modified by the person deploying Snikket. They only need to provide the domain name.
- Snikket also includes additional components that a modern chat service needs. For example, it includes a STUN/TURN server to ensure that audio/video calls work reliably (again, preconfigured).
- Snikket provides its own apps, which are tested and developed in sync with each other and with the server. This avoids the common problem of incompatibilities that occur when you have an open ecosystem such as XMPP, where different open-source project developers may develop features at different paces, leaving users to figure out which ones support which feature. It also solves the discoverability and decision fatigue for users (searching "Snikket" on an app store will get you an app that you know is compatible with your Snikket server, you don't have to go through a list of XMPP clients and figure out which one is suitable).
- Snikket servers are not designed to be open public servers (these are an administrative nightmare). Instead, your server is closed and private by default. As the admin, you choose who signs up to your server by sending invitation links. The invitations also serve to simplify the account setup process - no need to prompt users to "choose a server", etc. They just need to provide a username.
Projects such as Conversations differ by running a single public server (conversations.im) and guiding people to sign up on that server, or choose one of a long list of free public XMPP providers. In some cases that's all what you want. But onboarding a group of people that way is not fun (for example, they all have to share their addresses with the group add each other to their contact lists one-by-one - Snikket makes discovery of contacts within the same server automatic).
Beyond these things, Snikket is all open-source and XMPP. But there is a focus on making a good polished and secure "product", if you like, rather than supporting the entire diverse XMPP ecosystem which includes a range of software of varying quality (weekend projects and more recently, 100% vibe-coded clients). For example, Snikket servers require certain security and authentication features which some older codebases that have fallen far behind modern XMPP standards (think Pidgin, etc.) simply don't support today.
> it’s actually all based on prosody and conversations?
As mentioned, I develop Prosody. I also collaborate with the Conversations developer and other XMPP projects. There's nothing shady here. The goal is just to make a best-in-class XMPP project that solves one particular use case (and it was primarily my own use case to begin with of course - I wanted to move my family off WhatsApp).
This project is exactly what I hoped existed. Thanks!
Invite only isn't that unusual for personal/friend&family servers. The author also set that in their prosody config. The snikket client works with many different XMPP servers, why wouldn't it? As you mentioned it's based on Conversations and for iOS on Siskin.
ejabberd is so much easier to set up than prosody, especially containerized. I would highly recommend checking multiple servers out before settling on one tbh.
Obvious note but if you run this on anything other than your own computer it nullifies E2EE.
I've run an XMPP server in various states of professionalism for around 20 years now. From mom's basement all the way to a colocated server with a similar setup that's described in the post.
The only caveat I have not been able to solve is hosting an xmpp server for a different domain, like it's possible with email.
A client connecting the account joe.doe@example.ORG will find the server it wants to connect to via SRV to be , e.g., xmpp14.example.COM and expect a TLS certificate for "example.ORG" which that server does not have (nor can/should easily get) - which makes sense in a lot of ways, but limits the ways one can offer hosting services.
If anyone has creative solutions I'm all ears.
I know at least two services that offer hosting with your own domain: https://my.snikket.org/ and https://account.conversations.im/domain/ so I suppose it is not that complex to setup.
Correct, but that means you cannot share that domain securely with, let's say, a website. No ?
You need a certificate for the domain you are going to serve of course. You can get one with ACME DNS challenges pretty easily (I have my clients set up a CNAME for the _acme-challenge subdomain of their domain).
I worded that poorly.
Yes, that is of course correct. But that means that your clients have to trust you without technical safeguards, that you will not use this to get for certificates for purposes other than XMPP.
Which, in my mind, is a problem if the domain is not used just for XMPP, but lets say for a website as well.
You should be able to do that via DNS SRV entries.
_xmpp-client._tcp.domain.tld. TTL IN SRV priority weight port target
_xmpps-client._tcp.domain.tld. TTL IN SRV priority weight port target
example:
_xmpp-client._tcp.not-my-domain.com. 3599 IN SRV 5 0 5222 jabber.my-domain.com.
You could also build a reverse proxy setup. Then you wouldn't need the keys to the SSL certs. But that is probably overkill to run at your client: https://wiki.xmpp.org/web/Tech_pages/XEP-0368I don't think I have seen a client complain about the cert being for jabber.my-domain.com Which one is giving trouble there?
I've been hosting a ejabberd instance for a few people for almost a decade now. It just works, takes close to no resources and needs almost no maintenance - just some trivial config checkups when migrating to newer major releases.
Around the same time I tried hosting a Matrix server with Synapse, but quickly stopped. It consumed a lot of resources when doing almost nothing, and it stopped running after an upgrade with some non-obvious error message, so instead of reanimating it I just abandoned it and moved to matrix.org with my personal account.
> OMEMO is built on the same encryption that Signal uses, so I’m comfortable trusting it.
I'm not saying that you shouldn't trust OMEMO (we all have our own threat models), but OMEMO and Signal have fewer similarities that people often assume and has some important caveats [0].
Be aware that this post has known issues that the author is not interested in fixing. In their own words (in response to clarifications by one of the OMEMO folk):
"I'll make an edit later about the protocol version thing, but I'm not interested in having questions answered. My entire horse in this race is for evangelists to f** off and leave me alone. That's it. That's all I want." [censorship of profanity mine]
You won't find this quote in the article with Ctrl+F, it's in the screenshot, where they omitted the original constructive comment by one of the OMEMO contributors that they chose to moderate, which you can find here: https://www.moparisthebest.com/tim-henkes-omemo-response.txt
So, by all means, read the blog post. But just be aware that its ultimate goal was not to be an unbiased accurate technical article.
The post is an opinion piece and not a technical article for sure, but I'm not sure the takeaway from that quote is that the article is inaccurate, but rather they aren't really looking to start a conversation but rather state their opinions. It seems they've made multiple edits where they believe there are inaccuracies.
FWIW, I personally think Henke is correct to state that creating "...a product based on XMPP+OMEMO that, exactly like Signal, can only communicate with other Signal users and always has encryption on." would largely address most of the critiques (or at least the ones that bother me most), but that Soatok is also correct in concluding that the XMPP ecosystem and the way OMEMO is used in clients today does not meet their definition of "Signal competitor"[0], which I think is still a useful way to frame things.
[0] https://soatok.blog/2024/07/31/what-does-it-mean-to-be-a-sig...
Oh I can't get enough those blog posts written in such confident language that it's easy to filter them out instead of having to realize midway reading how wrong every bold claim they put forward is… :þ
I went all in on xmpp to replace my traditional cell communications (text and calls) about a year ago, using Snikket on a VPS for the server, jmp.chat for an phone->xmpp gateway service, and a data-only esim for connectivity.
From my experience the biggest pain point gets the least amount of discussion in this post and that is the client landscape. I'm on iOS so I tried Monal and Siskin IM as my primary mobile clients and Movim/Dino as my desktop clients.
While I truly appreciate the effort the maintainers put into these tools I have to admit that the UX for Moanl and Siskin IM leave a lot to be desired and if you're used to something like Whatsapp or Signal it will prove a significant barrier to convincing friends and family to adopt your new platform.
I frequently encountered UI bugs and missing features using the iOS clients and for the life of me could never get notifications working reliably on mobile (a constant bug bear for users in the Siskin and Snikket user base).
For calls and texts on mobile, I don't think I ever managed to get a reliable notification unless the application was open on the screen on iOS. This meant that I frequently missed important calls or texts when out and about. On the desktop, Dino did manage to at least always alert me when a call or a text came through, but answering the calls on was always hit or miss on my laptop for reasons that allude me.
Interestingly the most full featured and reliable client turned out to be movim, which has the caveat of being a full featured formum/social network with an xmpp client embedded. On movim I would reliably get notifications for calls and texts and could "answer" calls in any browser connected to a microphone easily.
Another thing to note if you're looking to replace your phone service is that 3G/LTE radio is very tolerant to maintaining a reliable connection on the move, jumping between cell towers. The same cannot be said for an XMPP based call, and you will encounter significant latency and drop outs trying to hold a conversation driving or on transit.
I eventually gave up on the venture after missing a few too many important notifications, but if I was to go defiantly go all in again I think I would focus on self hosting a movim instance as my base "client", as it was the most reliable and easy to use of all the ones I tried. For mobile, I did hear good things about Conversations on Android but never got around to trying that one.
Yeah, iOS is definitely a weaker spot and we're aware of it. Monal is currently working on an overhaul of their UI (they have a grant allocated for it: https://nlnet.nl/project/Monal-IM-UI/ ).
There is also a new app in the works between Cheogram and Snikket. There is a beta available, but it's still young (and we won't apply any Snikket branding until E2EE is complete).
Thanks for sharing your experience!
I’ve been running a matrix server for about 2 years for family. It’s… ok. Clients are bad. Right now nobody on iOS can send images because there is a bug in fluffychat preventing it. Kinda defeats the purpose of a chat for sharing baby pictures. Synapse is a beast. It’s basically taken over my entire VPS.
Joining rooms of various FOSS projects has been nice, but honestly I wish they’d all just stick to libera.chat
This article makes me wonder why we collectively ditched xmpp for matrix when it seems like the protocol is still miles ahead?
The XMPP vs Matrix question is really about where the complexity lives.
XMPP puts complexity in extensions (XEPs). The core protocol is simple but you need to cherry-pick which XEPs your server and clients support, leading to fragmentation. Two XMPP clients might support completely different feature sets.
Matrix puts complexity in the protocol itself - the DAG-based event graph for federation is elegant but expensive. Synapse eating your VPS is the direct consequence of that design choice. Every room maintains a full causal history, which is great for consistency guarantees but terrible for resource usage.
The ejabberd comment in this thread is telling - "just works, takes close to no resources, needs almost no maintenance" for almost a decade. That's the XMPP experience when you accept the tradeoffs.
I think we ditched XMPP not because Matrix was technically better, but because Matrix arrived with a better story at the right time: a single reference client (Element) that actually worked, a clear spec (not 400+ optional XEPs), and federation that felt more like email than like "hope your server supports the same extensions."
The irony is that both protocols now face the same existential problem: your contacts won't switch. The network effects of WhatsApp/Signal/iMessage are the real enemy, not protocol design.
> Two XMPP clients might support completely different feature sets.
This is of course true of Matrix as well. Just because you document everything in one place doesn't mean every app will support it all. Or that every app will even want to support it all. If every app were exactly the same there would be no point in having multiple apps, after all.
> The network effects of WhatsApp/Signal/iMessage are the real enemy, not protocol design.
Absolutely.
Don't know if it's still this way, but I had the exact same experience with the XEPs a decade ago. Even message history is an extension, but at least it has broad support. File transfer was much harder to get right.
The servers (ejabberd included) also all defaulted to a simpler but less secure config, so I would've appreciated a writeup like this post back then.
I am genuinely interested in hearing why we collectively ditched XMPP. I would love to hear someone who has been in the weeds on the development or even just following closely.
Edit: Seems someone beat me to it with a good reply.
XMPP had rather bad name. Well-known design issues causing message losses, fractioned ecosystem due to varying implementation of extensions, unsuitability for mobile clients, absence of synchronization between clients, absence of end-to-end encryption. Most of these issues were (much) later fixed by extensions, but Matrix (or Signal for those who do not require federated one) was already there, offering E2EE by default.
Even today, E2EE in XMPP is rather inconvenient compared to Matrix due to absence of chain-of-trust in key management.
> I am genuinely interested in hearing why we collectively ditched XMPP
We didn't. It was never very popular, and is today more popular that it has ever been.
Depends if you mean just the technology or using it in the small federated spirit. Google Talk and Facebook Messenger were XMPP all the way through and worked with vanilla XMPP clients. Slack wasn't XMPP but supported it via a gateway until it was dropped.
Not sure how popular the small federation was back then, but I know Mac OS X Server touted an XMPP server and that was a first-class feature of iChat.
It wasn’t popular? I remember using pidgin to talk to friends on google chat, facebook and my work contacts. It was glorious.
I haven’t had a reason to use an xmpp client in over a decade.
Likely you do or have without knowing it. The protocol is used in telecom quite a bit for all sorts of things. Jitsi is built on XMPP. Lots of games use it for chat - league of legends and unreal engine I believe. Xmpp shows up in all sorts of places if you look.
Same! Pidgin was such a great piece of software
Decent overview (& more broadly but the heart is about XMPP & good ol’ capitalist corpo greed): https://ploum.net/2023-06-23-how-to-kill-decentralised-netwo...
I don’t know. The only good solution would be if all messaging apps used the same protocol so everyone could be reached. But right now it is a mess. We can’t even message each other easily. It’s ridiculous. But what am I talking about? We can’t even agree on the same measurement units.
> The only good solution would be if all messaging apps used the same protocol so everyone could be reached.
That's exactly what XMPP was created to solve, an open standard that could be implemented by anyone. For a while it even looked like there was a chance for that to work out. Whatsapp, Google Talk, Cisco Jabber, and some others used to be based on XMPP.
Unfortunately it didn't quite pan out that way.
I ran ejabberd, later prosody for a while. Eventually I stopped because the contacts went away and it was just not easy enough to set up for ordinary people.
Sad because the idea of running a federated chat service for your family and them having all their contacts there, is great from a data ownership point of view.
Went back to use a mix of WhatsApp, Telegram, Signal and Messenger because apparently there is always some people not wanting to use one or the other service, or only using one of them.
Revive your prosody and set up https://slidge.im/ for Telegram, WhatsApp and Signal. It's not a proper solution I know, but at least you'll keep on using XMPP clients and they'll get better because they will have one more user at least. ;)
I grew up using XMPP (I'm 25), but today I use Briar and Signal. I use text and calls for my family, because no one else but me uses Signal so it's unfair for them to use one app to talk to me and no one else.
XMPP has been great to run on NixOS… the servers uses so few resources compared to something extremely heavy like Matrix. The Movim client has been wonderful too allowing users to have calls/sharing from chatrooms (MUCs)—supporting a pretty new XEP in the XMPP space—which means there’s no good reason to be on Discord anymore if you care about the freedom/privacy of yourself & your communities.
Google Talk and Facebook Messenger both used to be XMPP, and I used Pidgin for both, wonderful times...
I used to use iChat AV, which was amazing (I still miss it).
Facebook had an XMPP compatible bridge for a subset of their chat functions for awhile, but never "was XMPP".
WhatsApp OTOH still is a fork of XMPP.
Great writeup. I went through a very similar journey. Signal as the "good enough" default, then gradually wanting to own the whole stack. The bit about smacks and cloud_notify being essential for mobile is spot on, that was the part I always underestimated in past XMPP attempts. Without those two modules the experience is terrible on phones and it's no wonder people bounced off it.
One thing I'd add: if you're already running Caddy as your reverse proxy, you can use its on_demand TLS to handle certificates for the upload and conference subdomains automatically instead of managing them through certbot separately. Saves a moving part.
Curious how federation has been in practice. Are you actually messaging people on other servers, or is it mostly just you and contacts you've created accounts for?
If the premise contributing to the conclusion to run their own chat service is:
> But Signal is still one company running one service. If they shut down tomorrow or change direction, I’m back to square one.
Aren't they in the same boat now with Cloudflare and Let's Encrypt?
Yes, probably but they are “easily” replaced. More easily than Signal in any case.
Also if we go down this road, we’re all depending on our internet access provider at the very least too! At some point we gotta know when to stop trying to be fully independent from the rest of the world. He chose there.
There are obviously other CDNs (or whatever Cloudflare considers itself to be these days) and other certificate authorities. They are all interchangeable thanks to open protocols (HTTP, TLS/ACME in this case). Contrasted to Signal: there are no other implementations.
Not really. If their own their domain, then it's possible to swap out CF and LE for different companies.
That would certainly be a very annoying event, but not an unrecoverable one.
Give me linux-> mobile voice call and linux-> Linux screen share and I would be happy.
Also plugin for gif selector.
But other than that, my ejabberd instance has been running for years with no effort.
Have you tried the Movim client? https://movim.eu
Web client, but I think movim has GIF picker and screensharing features. It even does multiparty video calls, compatible with dino. Since it's P2P, it does not scale well to a lot of users, but the developer is working on SFU support for larger video calls.
> linux-> mobile voice
I've been using Dino on Linux to talk to Conversations/Monal with video and it's been working pretty well. Do you have a different experience ?
Hosting chat infrastructure is surprisingly hard, but the real challenges emerge beyond C10K+ scale.
So self-hosting federated instances like this is pretty interesting way to scale.
And still You have centalize system why not tox
Buried here is the fact that Gajim seems to have had big updates lately. I might just switch back to XMPP from Matrix, as all the matrix clients on Linux suck frankly. Conversations on Android is significantly better than any Matrix client I've used.
Have you used Fractal? It's not perfect, but it's a Linux client that works better than any other client I've used on mobile.
Agreed, I use fractal and a self-hosted server and it works great.
I've very recently try on my NixOS homeserver both Matrix and XMPP, with the target of having family/few friends own video-calls with chats aside mostly meant as shared scrap of text more than real chats to waste time on them. Something like "remember the milk" than else.
The experience was unpleasant in both cases; in the end, I have a working setup for both, relatively working at least, but what's really missing is a single application, something you can 'go install', 'pip install', or 'cargo build', also easy for distro packagers, that features:
- a text-based configuration
- an admin WebUI (for eventual storage cleanup, moderation etc)
- a client WebUI for users
including:
- text chat with optional file uploads
- audio/video chat
- other bits on the side like long-form notes Nostr-style for a blog with comments under articles etc (yes, it's connected, it's just plain textual communication).
The core of it is just a simple snippet of text, we can transmit to some privately, or to anyone openly, and in that sense, Nostr has got it spot on: you can do chats, emails, blog posts, because everything is just a bit of text rendered with any attached media. Unfortunately, as it stands, Nostr feels like an ecosystem that lacks a clear direction; XMPP seems to be largely abandoned, with enough complexity to put most people off; Matrix looks to be heading towards a commercial future riddled with issues that keep most people away, and in the end, we don't have much. Hosting BBB or Jitsi is even worse. Hosting Asterisk or Yate to use with softphones or classic VoIP desk phones is also problematic.
There's a lot going on under the bonnet now, but why an app hasn't emerged yet that brings together features we've more or less had for decades is a bit of a mystery to me. It almost feels intentional, as if it's designed to deny free communication to the masses by making life difficult on purpose.