191 lines
8.7 KiB
Markdown
191 lines
8.7 KiB
Markdown
---
|
|
title: "Trying Twenty: How does an Open Source CRM work?"
|
|
date: 2025-08-03T06:10:10+02:00
|
|
lastmod: 2025-11-17T12:10:10+02:00
|
|
draft: false
|
|
image: "uploads/twenty.png"
|
|
categories: [ 'English' ]
|
|
tags: [ 'crm', 'twenty', 'salesforce', 'django', 'self-hosting' ]
|
|
---
|
|
|
|
I spend my day working with Salesforce, a very, very feature-rich CRM that you pay big money to use.
|
|
Salesforce is the opposite of OpenSource and the many features are expensive. Salesforce business model is based on this
|
|
and on the lock-in effect.
|
|
If your company invested in implementing Salesforce, they'll likely pay a lot to keep it.
|
|
|
|
So what does an alternative look like? Let's have a look at [Twenty](https://twenty.com), an OpenSource CRM that
|
|
recently reached the magic 1.0 version.
|
|
|
|
# Getting started
|
|
|
|
There are two options of getting started: Register at [app.twenty.com](https://app.twenty.com) and start right away on
|
|
the devs instance or self-host Twenty on your own server.
|
|
I did the ladder, so let's discuss how that. The basic steps I took were
|
|
|
|
* point twenty.hyteck.de to a server
|
|
* Install traefik on the server (I cheated, traefik was already installed)
|
|
* Deploy [this docker-compose.yml](docker-compose.yml) with [this env file](env)
|
|
|
|
Then visit the domain and set up the first user.
|
|
|
|
# Features
|
|
|
|
Twenty offers an initial datamodel that you should be familiar from other CRMs. the standards objects are
|
|
|
|

|
|
|
|
* **Persons** A individual person. You can attach notes, E-Mails, etc..
|
|
* **Companies** The same for organizations. Organization websites must be unique
|
|
* **Opportunities** The classic opportunity with customizable stages
|
|
* **Notes** They can be attached to any of the objects above
|
|
* **Tasks** Items to work on
|
|
* **Workflows** Automations similar to Salesforce flows. E.g. you can create a task every time an Opportunity is
|
|
created.
|
|
|
|
The basic datamodel can be extended in the GUI. Here is how my "Company" model looks like
|
|
|
|

|
|
|
|
You can add any of the following fields to an object.
|
|
|
|

|
|
|
|
### Workflows
|
|
|
|
Workflows are Twenty's way of allowing users to build automations. You can start a Workflow when a Record is created,
|
|
updated or deleted. In addition, they can be started manually, on a schedule and via Webhook (yeah!).
|
|
|
|

|
|
|
|
You can then add nodes that trigger actions. Available right now are
|
|
|
|
* **Creating, updating or deleting a record**
|
|
* **Searching records**
|
|
* **Sending E-Mails** This is the only option to trigger e-mails so far
|
|
* **Code** Serverless Javascript functions
|
|
* **Form** The form will pop up on the user's screen when the workflow is launched from a manual trigger. For other
|
|
types of triggers, it will be displayed in the Workflow run record page.
|
|
* **HTTP request** Although possible via Code, this is a handy shortcut to trigger HTTP requests
|
|
|
|
What is currently completely missing are Foreach-loops
|
|
and [conditions](https://github.com/twentyhq/core-team-issues/issues/1265). I can not say "If Opportunity stage is
|
|
updated to X do Y else, do Z".
|
|
Without this, Workflows are really limited in their power.
|
|
|
|
What already seems quite mature though is the code option. It allows to put in arbitrary code and output a result.
|
|
|
|

|
|
|
|
I did not try a lot, but I assume most basic Javascript works. I successfully built an http request that send data to a
|
|
server.
|
|
|
|
If what you're doing is straightforward enough to not use loops and conditions or if you are okay with doing all of them
|
|
in the Code node, you can do basically anything.
|
|
|
|
## API
|
|
|
|
Twenty offers an extensive API that allows you to basically do everything. It's well documented and easy to use.
|
|
|
|
Here is an example of me, syncing Rescue Organizations from [notfellchen.org](https://notfellchen.org) to Twenty.
|
|
|
|
```python
|
|
import requests
|
|
|
|
from fellchensammlung.models import RescueOrganization
|
|
|
|
|
|
def sync_rescue_org_to_twenty(rescue_org: RescueOrganization, base_url, token: str):
|
|
if rescue_org.twenty_id:
|
|
update = True
|
|
else:
|
|
update = False
|
|
|
|
payload = {
|
|
"eMails": {
|
|
"primaryEmail": rescue_org.email,
|
|
"additionalEmails": None
|
|
},
|
|
"domainName": {
|
|
"primaryLinkLabel": rescue_org.website,
|
|
"primaryLinkUrl": rescue_org.website,
|
|
"additionalLinks": []
|
|
},
|
|
"name": rescue_org.name,
|
|
}
|
|
|
|
if rescue_org.location:
|
|
payload["address"] = {
|
|
"addressStreet1": f"{rescue_org.location.street} {rescue_org.location.housenumber}",
|
|
"addressCity": rescue_org.location.city,
|
|
"addressPostcode": rescue_org.location.postcode,
|
|
"addressCountry": rescue_org.location.countrycode,
|
|
"addressLat": rescue_org.location.latitude,
|
|
"addressLng": rescue_org.location.longitude,
|
|
}
|
|
headers = {
|
|
"Content-Type": "application/json",
|
|
"Authorization": f"Bearer {token}"
|
|
}
|
|
|
|
if update:
|
|
url = f"{base_url}/rest/companies/{rescue_org.twenty_id}"
|
|
response = requests.patch(url, json=payload, headers=headers)
|
|
assert response.status_code == 200
|
|
else:
|
|
url = f"{base_url}/rest/companies"
|
|
response = requests.post(url, json=payload, headers=headers)
|
|
assert response.status_code == 201
|
|
rescue_org.twenty_id = response.json()["data"]["createCompany"]["id"]
|
|
rescue_org.save()
|
|
|
|
|
|
```
|
|
|
|
#
|
|
|
|
# The Company, Business Model and Paid Features
|
|
|
|
The company behind Twenty is called "Twenty.com PBC" and mostly seems to consist of former AirBnB employees in Paris.
|
|
The company is probably backed by Venture Capital.
|
|
The current business model is to charge for using the company's instance of Twenty. It starts at 9\$/user/month without
|
|
enterprise features. SSO and support will cost you 19\$/user/month.
|
|
|
|
Selfhosting is free but SSO is locked behind an enterprise badge with seemingly no way to pay for activating it.
|
|
I suspect that in the future more features will become "Enterprise only" even when self-hosting. All contributors must
|
|
agree
|
|
to [a Contributor License Agreement (CLA)](https://github.com/twentyhq/twenty/blob/main/.github/CLA.md), therefore I
|
|
believe they could change the License in the future, including switching away from Open Source.
|
|
|
|
# AI Usage
|
|
|
|
The repo contains a `.cursor` directory and `CLAUDE.md` so I assume the devs make (heavy?) use of LLM generated code.
|
|
The ethical and legal problems with this are for you to decide. I don't know what effect this has on code quality, for
|
|
now I'd say things are sometimes buggy (failed upgrades) and UX could be better tested (looking at the e-mail
|
|
integration) - if this is due to AI slop I don't know.
|
|
|
|
# Conclusion
|
|
|
|
Twenty is a really promising start of building a good CRM. The ease of customizing the datamodel,
|
|
using the API and a solid beginning to Flows allows users to get a lot of value from it already.
|
|
Flows need some more work to become as powerful as they should be and the E-Mail integration needs to get better.
|
|
|
|
Stating the obvious: This is not something that could ever replace Salesforce. However, there are many organizations
|
|
that would benefit a lot from a CRM like Twenty, they simply don't need, can't handle or don't want to pay for all the
|
|
features other CRMs like Salesforce offer.
|
|
|
|
If Twenty continues to focus on small to medium companies and the right mix of standard features vs. custom development
|
|
options I see a path where it becomes a solid choice for these companies. On the other hand there are the usual problems
|
|
of VC-backed OSS development, and we shall see how it goes for them. Unless there is a strong userbase that credibly
|
|
threatens a hard fork, enshittification could start soon.
|
|
|
|
# Addendum: Important Features
|
|
|
|
Here is a short list of features I missed and their place on the roadmap if they have one
|
|
|
|
* **Compose & Send E-Mails**
|
|
Planned [Q4 2025](https://github.com/orgs/twentyhq/projects/1?pane=issue&itemId=106097937&issue=twentyhq%7Ccore-team-issues%7C811)
|
|
* **Foreach loops in Workflows
|
|
** [Q3 2025](https://github.com/orgs/twentyhq/projects/1/views/33?pane=issue&itemId=93150024&issue=twentyhq%7Ccore-team-issues%7C21)
|
|
* **Conditions in Flows
|
|
** [Q4 2025](https://github.com/orgs/twentyhq/projects/1/views/33?pane=issue&itemId=121287765&issue=twentyhq%7Ccore-team-issues%7C1265)
|