Turso: a SQLite rewrite in rust with an MIT license
Still in beta. Was made aware of it by this video
Still in beta. Was made aware of it by this video
The most important part of FLOSS is "F", apparently.
For those outside the loop: rsync starting using AI agents to handle the influx of AI security reports to improve the test suite and fix bugs. It introduced a few CVEs and people who never contributed in any way started firing shots at the maintainer.
rsync maintainer's response to the people getting pissy about his usage of AI: medium and the related post on programming.dev
https://mikemcquaid.com/open-source-maintainers-owe-you-nothing/Open linkView original on programming.devSome people talk about mailing lists with a lot of reverence, but I have only ever found them to be extremely ugly and unreadable.
Are there any good clients out there that make them readable? For example a lemmy-like, threaded interface with interactivity? Or for PR/MRs an interface that shows the diffs with syntax highlighting, toggleable unified and side by side diff views, ability to comment within diffs and continue discussions within them (maybe even threaded)?
I've heard and read variations of this a lot. GitHub never was simply a git frontend. It always had a community and artefacts around the code.
When Github was stable and well loved, people defended it all the time. It was the place to upload code, find contributors, and (after Microslop bought it) even funding for those lucky few popular enough to get it. I understand that change is hard but GitHub's trajectory was written in stone the second Microslop bought it.
Of course, letting go of something is difficult, especially if it feels simple to use and everybody else seems to be using it. But when cracks start to show, the minority will react. The majority will simply tolerate enshittification and reject anything else, for many reasons. Some are valid, some not, it's perspective sometimes.
However, claiming that moving away from Github is easy because git is decentralised... that's either a profound lack of understanding or a bad faith argument. Maybe even both. If you honestly think that's the case, go see how fun it is to contribute to the Linux kernel (or any project using mailing lists). Go to a project hosted on Git Web and try to submit a bug report.
There is hope for one GitHub alternative in particular with a highly unfortunate name for reason I won't get into: forgejo. They have been trying for years to build a federated gitforge (without much success unfortunately), but hope might be on the horizon as Europe starts down the path of leaving foreign Big Tech behind. The Netherlands wants to contribute to forgejo.
Gitlab, another GitHub alternative, has many French institutions as customers, but they have done their absolute best to ignore any requests for federation support. Instead, they've jumped onto the bandwagon and gone all in on AI. Don't expect any progress on that front any time soon.
As stated before, GitHub has many things besides git, the biggest one is the community. But to contribute, you need to create an account Microslop's platform. You cannot use that account for smooth experience once you move to an alternative. You can login with it, but that's about it.
Without federation, any alternative is fighting an already immense uphill battle. When you create your user with your repositories on ALTERNATIVE SERVER that cannot connect to ANOTHER SERVER, which forces you to create accounts on every other server.
Federation would solve that. You could search, find and contribute to repositories on the fediverse. It could (hopefully) put a dent in GitHub's omnipresence and allow for users to migrate away once, without creating accounts everywhere. Normal users could also contribute straight from the fediverse without having to create an account on Github first.
Let's hope European countries fund forgejo instead of forking it or starting a completely new project.
Desktop web-apps won. Simply because native UI libraries never evolved past their 90s days. Either the UI is defined in some DSL, that's loaded (or compiled) and then you spend most of the time writing getElement(pathToElement) and wiring it up, or you have to boilerplate create each element and parent.addChild(element).
And wiring it up is also a pain. Send a signal or event, add a listener or slot, or whatever fancy name each framework comes up with, and if you have to modify another element, it means querying for it, or having a singleton, or passing a reference/pointer, or whatever. It's so friggin-old school.
In the meanwhile, the web discovered reactivity, components, declaring the UI and having the logic in the same file, live debugging, tight development loops, and so much more.
Is it just too difficult for native frameworks? Is it a sunken cost issue or fear of breaking backwards compatibility? Why can't native UI development be as easy and approachable as web dev?
Don't get me wrong, I need webdev like a child needs cancer, but I've tried Slint, imGUi, Qt, Gtk, wxWidgets, and more and the experience makes me want to blow my brains out every single time. I dread writing any native GUI that I got desperate enough to try writing a TUI but that's unbelievably worse!
It's gotten so bad, that Tauri and Dioxus are now on the menu. I never wanted to mix web dev into my native applications, but it feels like the abominably anachronistic state of native UI development is just forcing not only me, but anybody who wants to have a good experience writing native UI apps (especially those that are multi-platform), to use a fucking web view! A memory-hogging web view!
I've tried FairEMail and SimpleEmail, but they require opening the app to see emails. They seem to be forks or versions of each other without background syncing and (sorry) a terribly ugly interface. Neither seem to have filters.
Background syncing shouldn't be constantly on, just every 5-10 minutes or so. Normally I check once a day, but forget to quite easily and then miss an email. If it checked automatically even twice daily, that'd be enough.
The maker of Ghostty and Hashicorp is finally leaving Github.
"the_yank_stank" has nothing to do with programming or tech and the user just started posting news about child rape or something.
Framework released a love letter to Apple.
https://odysee.com/@samtime:14/apple-reacts-to-the-framework-pro:9Open linkView original on programming.devcross-posted from: https://programming.dev/post/49000591
TL;DR fetchmail to move all emails from email provider to local mailbox that is then served via IMAP by dovecot
Hi, I like being able to switch between email providers easily without having to change my email address (related post). For example right now people have to go through the hassle of going from
[email protected]to[email protected]. It's a big barrier because you now have to update that email address everywhere. Imagine having everything on gmail and then moving to startmail, fastmail, posteo, or whatever else.A solution I was made aware of is to:
- pay for a domain e.g
mydomain.orgfor 10 years (can be cheap)- use their inbuilt email (sometimes free) or pick an email provider that allows custom domains
- pull all the email to server you host
- serve that email
That way, you will have your
[email protected]and switch email providers underneath while keeping all your emails.Example config
This config uses the module I wrote (maybe something else exists, but I couldn't find it). It pulls emails of
[email protected]frompop.remote.hosttomy.hostand exposes them via IMAPS as[email protected]onmy.host.Notice that
my.domainneed not be the same asmy.host. This allows me to hide my IMAP server. Somebody looking at theMXrecord ofmy.domainwon't immediately find the IMAP server.{ config, ... }: { /** configuration to for fetchmail to retrieve from the remote host emails will be moved into a the **local** mailbox of a user with the same email address */ environment.etc."mail/fetchmailrc" = { text = '' poll pop.remote.host protocol pop3 port 995: user "[email protected]" with password "passwordWithouQuotes" is vmail here options fetchall ssl mda "dovecot-deliver -d [email protected]" ''; user = config.services.email-fetch-serve.daemonUser; group = config.services.email-fetch-serve.daemonGroup; }; /** usernames and passwords used to log into the **self-hosted** IMAP service Uses same format as /etc/passwd https://doc.dovecot.org/2.4.3/core/config/auth/databases/passwd_file.html */ environment.etc."mail/imap.passwd" = { text = '' [email protected]:{plain}password ''; user = config.services.email-fetch-serve.daemonUser; group = config.services.email-fetch-serve.daemonGroup; }; services.email-fetch-serve = { enable = true; sslCertPath = "/var/acme/certs/mydomain.crt"; sslCertKey = "/var/acme/certs/mydomain.key"; fetchmailRcPath = "/etc/mail/fetchmailrc"; imap = { port = 993; openFirewall = true; passdb = "/etc/mail/imap.passwd"; }; }; }::: spoiler the module
{ config, lib, pkgs, ... }: let cfg = config.services.email-fetch-serve; daemonUserHome = "/var/spool/${cfg.daemonUser}"; sslEnabled = (cfg.sslCertPath != null) && (cfg.sslCertKey != null); /** Used by fetchmail to deliver mail to dovecot */ dovecot-deliver-wrapper = pkgs.writeShellScriptBin "dovecot-deliver" ''${pkgs.dovecot}/libexec/dovecot/deliver "''${@}"''; in { /** A self-hosted "email relay" that allows fetching emails from a server and then serving it via IMAP. Emails are retrieved with fetchmail and exposed via dovecot. By default, dovecot used IMAP which unencrypted, but with an ssl certificate and key, it can be encrypted and thus turned into IMAPS. To generate SSL certs, the `security.acme` option is powerful, but you can also use a self-signed certificate. To store secrets, do consider using - agenix: https://github.com/ryantm/agenix - sopsnix: https://github.com/Mic92/sops-nix */ options = with lib; { services.email-fetch-serve = { enable = mkEnableOption "emails from an email server and serve them via IMAP"; sslCertPath = mkOption { type = types.nullOr types.externalPath; description = "Giving a path to an SSL cert **and** key will enable IMAPS and disable IMAP"; default = null; }; sslCertKey = mkOption { type = types.nullOr types.externalPath; description = "Giving a path to an SSL key **and** cert will enable IMAPS and disable IMAP"; default = null; }; fetchmailRcPath = mkOption { type = types.externalPath; description = "Configuration for fetchmail"; example = '' poll pop.remote.host protocol pop3 port 995: user "[email protected]" with password "passwordWithouQuotes" is vmail here options fetchall ssl mda "dovecot-deliver -d [email protected]" ''; }; imap = { port = mkOption { type = types.int; description = '' Which port to host the IMAP service on. If sslCertPath is set this will be the port of othe IMAPS service''; default = 143; # Default IMAP port }; openFirewall = lib.mkOption { type = lib.types.bool; default = false; example = true; description = "Allow external traffic to reach the IMAP(S) port"; }; passdb = mkOption { type = types.externalPath; description = '' Where passwords for IMAP are stored. Should be secret and accessible by vmail user https://doc.dovecot.org/2.4.3/core/config/auth/databases/passwd_file.html https://doc.dovecot.org/2.4.3/core/config/auth/passdb.html ''; }; }; daemonUser = mkOption { type = types.str; description = "Name of the user running the daemons"; default = "vmail"; }; daemonGroup = mkOption { type = types.str; description = "Name of the user's group running the daemons"; default = "vmail"; }; }; }; config = lib.mkIf cfg.enable { assertions = [ { # Either both SSL vars are set or none are set assertion = (cfg.sslCertPath == null && cfg.sslCertKey == null) || (cfg.sslCertPath != null && cfg.sslCertKey != null); message = "email-fetch-serve service must have sslCertPath AND sslCertKey to have functional SSL"; } ]; # How electronic email works # https://tldp.org/HOWTO/Mail-Administrator-HOWTO-3.html # ${daemonUserHome} needs to be created and owned by vmail users.users."${cfg.daemonUser}" = { createHome = true; home = daemonUserHome; group = cfg.daemonGroup; isSystemUser = true; }; users.groups."${cfg.daemonGroup}" = { }; services.dovecot2 = lib.mkMerge [ ({ # Taken and adapted from https://wiki.nixos.org/wiki/Dovecot enable = cfg.enable; createMailUser = true; enableImap = true; mailUser = cfg.daemonUser; mailGroup = cfg.daemonGroup; # implement virtual users # https://doc.dovecot.org/2.3/configuration_manual/howto/simple_virtual_install/ # store virtual mail under # /var/spool/mail/vmail/<DOMAIN>/<USER>/Maildir/ mailLocation = "maildir:~/Maildir"; mailboxes = { # use rfc standard https://apple.stackexchange.com/a/201346 All = { auto = "create"; autoexpunge = null; specialUse = "All"; }; Archive = { auto = "create"; autoexpunge = null; specialUse = "Archive"; }; Drafts = { auto = "create"; autoexpunge = null; specialUse = "Drafts"; }; Flagged = { auto = "create"; autoexpunge = null; specialUse = "Flagged"; }; Junk = { auto = "create"; autoexpunge = "60d"; specialUse = "Junk"; }; Sent = { auto = "create"; autoexpunge = null; specialUse = "Sent"; }; Trash = { auto = "create"; autoexpunge = "60d"; specialUse = "Trash"; }; }; extraConfig = lib.concatStrings [ '' # force to use full user name plus domain name # for disambiguation auth_username_format = %Lu # Authentication configuration: auth_mechanisms = plain passdb { driver = passwd-file args = ${cfg.imap.passdb} } userdb { driver = static # the full e-mail address inside passwd-file is the username (%u) # [email protected] # %d for domain_name %n for user_name args = uid=${cfg.daemonUser} gid=${cfg.daemonGroup} username_format=%u home=${daemonUserHome}/%d/%n } '' (lib.optionalString (!sslEnabled) '' service imap-login { inet_listener imap { port = ${builtins.toString cfg.imap.port} } inet_listener imaps { port = 0 } '') (lib.optionalString (sslEnabled) '' service imap-login { inet_listener imap { port = 0 } inet_listener imaps { port = ${builtins.toString cfg.imap.port} } }'') ]; }) (lib.mkIf sslEnabled { sslServerCert = cfg.sslCertPath; sslServerKey = cfg.sslCertKey; }) ]; # Open the firewall port to be able to be contacted networking.firewall.allowedTCPPorts = [ cfg.imap.port ]; networking.firewall.allowedUDPPorts = [ cfg.imap.port ]; ##################### # To fetch the emails systemd.services.fetchmail = { enable = cfg.enable; after = [ "dovecot2.service" ]; wantedBy = [ "dovecot2.service" ]; path = [ dovecot-deliver-wrapper ]; serviceConfig = { User = cfg.daemonUser; ExecStart = "${pkgs.fetchmail}/bin/fetchmail --fetchmailrc ${cfg.fetchmailRcPath} --daemon 60"; }; }; }; }:::
TL;DR fetchmail to move all emails from email provider to local mailbox that is then served via IMAP by dovecot
Hi, I like being able to switch between email providers easily without having to change my email address (related post). For example right now people have to go through the hassle of going from [email protected] to [email protected]. It's a big barrier because you now have to update that email address everywhere. Imagine having everything on gmail and then moving to startmail, fastmail, posteo, or whatever else.
A solution I was made aware of is to:
mydomain.org for 10 years (can be cheap)That way, you will have your [email protected] and switch email providers underneath while keeping all your emails.
Example config
This config uses the module I wrote (maybe something else exists, but I couldn't find it). It pulls emails of [email protected] from pop.remote.host to my.host and exposes them via IMAPS as [email protected] on my.host.
Notice that my.domain need not be the same as my.host. This allows me to hide my IMAP server. Somebody looking at the MX record of my.domain won't immediately find the IMAP server.
{ config, ... }:
{
/**
configuration to for fetchmail to retrieve from the remote host
emails will be moved into a the **local** mailbox of a user with the same email address
*/
environment.etc."mail/fetchmailrc" = {
text = ''
poll pop.remote.host protocol pop3 port 995:
user "[email protected]" with password "passwordWithouQuotes" is vmail here
options fetchall
ssl
mda "dovecot-deliver -d [email protected]"
'';
user = config.services.email-fetch-serve.daemonUser;
group = config.services.email-fetch-serve.daemonGroup;
};
/**
usernames and passwords used to log into the **self-hosted** IMAP service
Uses same format as /etc/passwd
https://doc.dovecot.org/2.4.3/core/config/auth/databases/passwd_file.html
*/
environment.etc."mail/imap.passwd" = {
text = ''
[email protected]:{plain}password
'';
user = config.services.email-fetch-serve.daemonUser;
group = config.services.email-fetch-serve.daemonGroup;
};
services.email-fetch-serve = {
enable = true;
sslCertPath = "/var/acme/certs/mydomain.crt";
sslCertKey = "/var/acme/certs/mydomain.key";
fetchmailRcPath = "/etc/mail/fetchmailrc";
imap = {
port = 993;
openFirewall = true;
passdb = "/etc/mail/imap.passwd";
};
};
}
::: spoiler the module
{
config,
lib,
pkgs,
...
}:
let
cfg = config.services.email-fetch-serve;
daemonUserHome = "/var/spool/${cfg.daemonUser}";
sslEnabled = (cfg.sslCertPath != null) && (cfg.sslCertKey != null);
/**
Used by fetchmail to deliver mail to dovecot
*/
dovecot-deliver-wrapper = pkgs.writeShellScriptBin "dovecot-deliver" ''${pkgs.dovecot}/libexec/dovecot/deliver "''${@}"'';
in
{
/**
A self-hosted "email relay" that allows fetching emails from a server and then serving it
via IMAP.
Emails are retrieved with fetchmail and exposed via dovecot.
By default, dovecot used IMAP which unencrypted, but with an ssl certificate and key, it can
be encrypted and thus turned into IMAPS.
To generate SSL certs, the `security.acme` option is powerful, but you can also use a
self-signed certificate.
To store secrets, do consider using
- agenix: https://github.com/ryantm/agenix
- sopsnix: https://github.com/Mic92/sops-nix
*/
options = with lib; {
services.email-fetch-serve = {
enable = mkEnableOption "emails from an email server and serve them via IMAP";
sslCertPath = mkOption {
type = types.nullOr types.externalPath;
description = "Giving a path to an SSL cert **and** key will enable IMAPS and disable IMAP";
default = null;
};
sslCertKey = mkOption {
type = types.nullOr types.externalPath;
description = "Giving a path to an SSL key **and** cert will enable IMAPS and disable IMAP";
default = null;
};
fetchmailRcPath = mkOption {
type = types.externalPath;
description = "Configuration for fetchmail";
example = ''
poll pop.remote.host protocol pop3 port 995:
user "[email protected]" with password "passwordWithouQuotes" is vmail here
options fetchall
ssl
mda "dovecot-deliver -d [email protected]"
'';
};
imap = {
port = mkOption {
type = types.int;
description = ''
Which port to host the IMAP service on. If sslCertPath is set this will
be the port of othe IMAPS service'';
default = 143; # Default IMAP port
};
openFirewall = lib.mkOption {
type = lib.types.bool;
default = false;
example = true;
description = "Allow external traffic to reach the IMAP(S) port";
};
passdb = mkOption {
type = types.externalPath;
description = ''
Where passwords for IMAP are stored. Should be secret and accessible by vmail user
https://doc.dovecot.org/2.4.3/core/config/auth/databases/passwd_file.html
https://doc.dovecot.org/2.4.3/core/config/auth/passdb.html
'';
};
};
daemonUser = mkOption {
type = types.str;
description = "Name of the user running the daemons";
default = "vmail";
};
daemonGroup = mkOption {
type = types.str;
description = "Name of the user's group running the daemons";
default = "vmail";
};
};
};
config = lib.mkIf cfg.enable {
assertions = [
{
# Either both SSL vars are set or none are set
assertion =
(cfg.sslCertPath == null && cfg.sslCertKey == null)
|| (cfg.sslCertPath != null && cfg.sslCertKey != null);
message = "email-fetch-serve service must have sslCertPath AND sslCertKey to have functional SSL";
}
];
# How electronic email works
# https://tldp.org/HOWTO/Mail-Administrator-HOWTO-3.html
# ${daemonUserHome} needs to be created and owned by vmail
users.users."${cfg.daemonUser}" = {
createHome = true;
home = daemonUserHome;
group = cfg.daemonGroup;
isSystemUser = true;
};
users.groups."${cfg.daemonGroup}" = { };
services.dovecot2 = lib.mkMerge [
({
# Taken and adapted from https://wiki.nixos.org/wiki/Dovecot
enable = cfg.enable;
createMailUser = true;
enableImap = true;
mailUser = cfg.daemonUser;
mailGroup = cfg.daemonGroup;
# implement virtual users
# https://doc.dovecot.org/2.3/configuration_manual/howto/simple_virtual_install/
# store virtual mail under
# /var/spool/mail/vmail/<DOMAIN>/<USER>/Maildir/
mailLocation = "maildir:~/Maildir";
mailboxes = {
# use rfc standard https://apple.stackexchange.com/a/201346
All = {
auto = "create";
autoexpunge = null;
specialUse = "All";
};
Archive = {
auto = "create";
autoexpunge = null;
specialUse = "Archive";
};
Drafts = {
auto = "create";
autoexpunge = null;
specialUse = "Drafts";
};
Flagged = {
auto = "create";
autoexpunge = null;
specialUse = "Flagged";
};
Junk = {
auto = "create";
autoexpunge = "60d";
specialUse = "Junk";
};
Sent = {
auto = "create";
autoexpunge = null;
specialUse = "Sent";
};
Trash = {
auto = "create";
autoexpunge = "60d";
specialUse = "Trash";
};
};
extraConfig = lib.concatStrings [
''
# force to use full user name plus domain name
# for disambiguation
auth_username_format = %Lu
# Authentication configuration:
auth_mechanisms = plain
passdb {
driver = passwd-file
args = ${cfg.imap.passdb}
}
userdb {
driver = static
# the full e-mail address inside passwd-file is the username (%u)
# [email protected]
# %d for domain_name %n for user_name
args = uid=${cfg.daemonUser} gid=${cfg.daemonGroup} username_format=%u home=${daemonUserHome}/%d/%n
}
''
(lib.optionalString (!sslEnabled) ''
service imap-login {
inet_listener imap {
port = ${builtins.toString cfg.imap.port}
}
inet_listener imaps {
port = 0
}
'')
(lib.optionalString (sslEnabled) ''
service imap-login {
inet_listener imap {
port = 0
}
inet_listener imaps {
port = ${builtins.toString cfg.imap.port}
}
}'')
];
})
(lib.mkIf sslEnabled {
sslServerCert = cfg.sslCertPath;
sslServerKey = cfg.sslCertKey;
})
];
# Open the firewall port to be able to be contacted
networking.firewall.allowedTCPPorts = [ cfg.imap.port ];
networking.firewall.allowedUDPPorts = [ cfg.imap.port ];
#####################
# To fetch the emails
systemd.services.fetchmail = {
enable = cfg.enable;
after = [ "dovecot2.service" ];
wantedBy = [ "dovecot2.service" ];
path = [ dovecot-deliver-wrapper ];
serviceConfig = {
User = cfg.daemonUser;
ExecStart = "${pkgs.fetchmail}/bin/fetchmail --fetchmailrc ${cfg.fetchmailRcPath} --daemon 60";
};
};
};
}
:::
Opensource is undeniably a boon to the world. Without it, not only would there be few to no viable options to tech giants, competition would be rendered much more difficult. Fledgling companies would either have to pay for licensed code or implement everything themselves and that would lock out many from even starting companies and dare I say it, even programming as a whole.
But for all the good it has done, there is one thing (amongst many others) that irks me about the opensource community: the phrase "why don't you just...". It is uttered so easily and so thoughtlessly, as if the other person is either too dumb to have considered it, too lazy to have looked it up, or just unwilling to admit it's the right way to do things.
We could go on and on. Yes, of course, people new to opensource or software in general have trouble voicing their thoughts and approaching problems in the way we software developers are used to. We have experienced the pain of having to track down the source of a bug, had to dig through somebody else's code, read terrible documentation (and consider ourselves lucky it even exists), basically, we have been through the baptism of fire.
Having gone through the hardships, we forget what it was like when we first started and what it was like to acquire the knowledge we have. To some, going through the fire must be the only way because "if I suffered, so should you"; a self-righteous, unsympathetic notion I wholeheartedly loathe.
Some might not actually mean it badly, but "just" don't know how to express themselves better. To those who do actually want to help and not sound belittling, please do consider alternative wording:
If you are one of those people though who genuinely don't see a problem with it, why don't you just understand?
There are a few opensource games out there, but many aren't in distro repos, or for windows, or released on itch.io requiring an account to download, etc. What could a open source game store for opensource games for all distros look like?
Solution: FetchMail + Dovecot. Just need to set it up, but it's pretty much what I was looking for.
The goal is to allow easily moving away from an email provider e.g from protonmail to tutanota or fastmail or whatever. How do people achieve this?
I just want to have myname@mydomain, the emails to go to whichever managed email service that allows it, and to then grab everything from that service with POP to then self-host a proxy that multiple devices can connect to. STMP can go either to my hosted server or the managed host, doesn't matter.
The idea is explicitly not to do the job of a managed email service. No DKIM, no SPF, no DMARC, none of that.
Distro is NixOS, but can adapt any instructions given. Mentioning just in case somebody already has a nix configuration with this setup.
People's websites get pummeled by LLM companies scraping the web. I bet they don't use nor scrape I2P though. Would using eepsites be a remedy?
And that without calling in twice. Laptop cameras as normally very crap. They say "1080p", but most of the time they are 720p or less and have maybe 2 megapixels or less. Phones have way more and can be connected to the laptop via USB. There must be a way to use their camera over USB, right?
I know of USB over LAN, so surely this is possible.
Thanks to everybody. In the end I went with Scrcpy.
Can't wait for the virus that uses this to replace a windows install with a Linux install that's riced to look like windows. Will the normies even notice?
https://odysee.com/@AlphaNerd:8d/installing-linux-just-got-easier:cOpen linkView original on programming.devWhy aren't people moving away from Github? There's Codeberg, Gitlab, and radicle. What's holding them back?
To make it clear to those who are misunderstanding: that's a list of companies that host matrix for you. They do it at a good price.
If you and your friends chip, it'll be a few bucks a pop per month to have your own private server with voice chat rooms and video chat rooms.
It's all opensource and contributes to the ecosystem. Best of all, no age verification because the data is yours.
https://matrix.org/ecosystem/hosting/Open linkView original on programming.dev