The open-source manufacturing ERP/MES/QMS. Perfect for complex assembly, HMLV, and configure to order manufacturing. - crbnos/carbon
We built Carbon after years of building end-to-end manufacturing systems with off-the-shelf solutions. We realized that:
We built Carbon to solve these problems ☝️.
Carbon is designed to make it easy for you to extend the platform by building your own apps through our API. We provide some examples to get you started in the examples folder.
Features:
Technical highlights:
The monorepo follows the Turborepo convention of grouping packages into one of two folders.
/apps for applications/packages for shared code| Package Name | Description | Local Command |
|---|---|---|
erp |
ERP Application | npm run dev |
mes |
MES | npm run dev:mes |
academy |
Academy | npm run dev:academy |
starter |
Starter | npm run dev:starter |
| Package Name | Description |
|---|---|
eslint-config-carbon |
Shared, extendable eslint configuration for apps and packages |
@carbon/database |
Database schema, migrations and types |
@carbon/documents |
Transactional PDFs and email templates |
@carbon/integrations |
Integration definitions and configurations |
@carbon/jest |
Jest preset configuration shared across apps and packages |
@carbon/jobs |
Background jobs and workers |
@carbon/logger |
Shared logger used across apps |
@carbon/react |
Shared web-based UI components |
@carbon/kv |
Redis cache client |
@carbon/lib |
Third-party client libraries (slack, resend) |
@carbon/stripe |
Stripe integration |
@carbon/tsconfig |
Shared, extendable tsconfig configuration used across apps and packages |
@carbon/utils |
Shared utility functions used across apps and packages |
Make sure that you have Docker installed on your system since this monorepo uses the Docker for local development.
In addition you must configure the following external services:
Each of these services has a free tier which should be plenty to support local development. If you're self hosting, and you don't want to use Upstash or Posthog, it's pretty easy to replace upstash with a redis container in @carbon/kv and remove the Posthog analytics.
First download and initialize the repository dependencies.
$ nvm use # use node v20
$ npm install # install dependencies
$ npm run db:start # pull and run the containersCreate an .env file and copy the contents of .env.example file into it
$ cp ./.env.example ./.envnpm run db:start to set the supabase entries:SUPABASE_SERVICE_ROLE_KEY=[service_role key]SUPABASE_ANON_KEY=[anon key]UPSTASH_REDIS_REST_URL=[UPSTASH_REDIS_REST_URL]UPSTASH_REDIS_REST_TOKEN=[UPSTASH_REDIS_REST_TOKEN]Environments & API Keys section:TRIGGER_PUBLIC_API_KEY=[Public 'dev' API Key, starting 'pk_dev*']TRIGGER_API_KEY=[Server 'dev' API Key, starting 'tr_dev*']POSTHOG_API_HOST=[https://[region].posthog.com]POSTHOG_PROJECT_PUBLIC_KEY=[Project API Key starting 'phc*']STRIPE_SECRET_KEY from the Stripe admin interface, and then run npm run -w @carbon/stripe register:stripe to get a STRIP_WEBHOOK_SECRETSTRIPE_SECRET_KEY="sk_test_*************"STRIP_WEBHOOK_SECRET="whsec_************"Then you can run the following:
$ npm run db:build # run db migrations and seed script
$ npm run build # build the packagesFinally, start the apps and packages:
$ npm run dev
$ npm run dev:mes # npm run dev in all apps & packagesYou can now sign in with:
username: your-email@address.com password: carbon
After installation you should be able run the apps locally.
To kill the database containers in a non-recoverable way, you can run:
$ npm run db:kill # stop and delete all database containersTo restart and reseed the database, you can run:
$ npm run db:build # runs db:kill, db:start, and setupTo run a particular application, use the -w workspace flag.
For example, to run test command in the @carbon/react package you can run:
$ npm run test -w @carbon/react
The API documentation is located in the ERP app at ${ERP}/x/api/js/intro. It is auto-generated based on changes to the database.
There are two ways to use the API:
Navigate to settings in the ERP to generate an API key. If you're self-hosting you can also use the supabase service key instead of the public key for root access. In that case you don't needto include the carbon-key header.
import { Database } from "@carbon/database";
import { createClient } from "@supabase/supabase-js"; const apiKey = process.env.CARBON_API_KEY;
const apiUrl = process.env.CARBON_API_URL;
const publicKey = process.env.CARBON_PUBLIC_KEY; const carbon = createClient<Database>(apiUrl, publicKey, { global: { headers: { "carbon-key": apiKey, }, },
}); // returns items from the company associated with the api key
const { data, error } = await carbon.from("item").select("*");import { getCarbonServiceRole } from "@carbon/auth";
const carbon = getCarbonServiceRole(); // returns all items across companies
const { data, error } = await carbon.from("item").select("*"); // returns items from a specific company
const companyId = "xyz";
const { data, error } = await carbon .from("item") .select("*") .eq("companyId", companyId);First off, congrats, this is no small feat, well done.
A question: in my (limited) experience, ERPs are made on the basis of integrations. I'd have thought the best priority order would be data-model first, integration second, everything else third. How do you think about this? What's the goal here?
And secondly, some feedback: It looks like Carbon falls into the same trap as many self-hostable SaaS-like products (including my own!), and that is that software designed for one single hoster is often more complex to deploy and built in a different way, whereas software designed primarily to self-host looks much simpler. As an example, installing Wordpress or Odoo is relatively simple, with basic frontend webserver config and easy to run open source databases. Carbon on the other hand appears to be quite a few different components, with many dependencies, some of which are SaaS products, and uses a database (Supabase) which is itself a whole microservice ecosystem that is a considerable effort to deploy. What's the strategy here? Despite having the skills for it, I'm not sure I'd ever consider self-hosting Carbon, and maybe that's good for Carbon as a business, but it's also less good for the ecosystem.
I was involved in all things ERP years ago. One thing I noticed was that the National Retail Association of the USA (the other NRA) have specification documents which would be perfect for basing both data models and transforms off. It seems all the big players tend to have almost, but not quite compatible models. It's very frustrating. We're talking SAP, Infor, MS, everyone. The amount of glue code I had to write to get various point of sale, accounting, BI, label printing etc software to work is astounding.
I guess that's how they make the money. Sell the platform and profit off the custom code.
This resonates with me a lot. Can I contact you? My email is in my profile.
Feel free, my email is my HN username at gmail. As I mentioned in a sibling comment, I'm not in tech anymore (except for fun) but I'm happy to provide any insights or advice to any questions you may have. I last worked with ERP systems about 10 years ago, but the thing about these systems is that they don't really change, so hopefully my knowledge is still helpful!
As a quick summary, this is mostly all ETL (Extract, Transform, Load). Learn the lowest practical level language you can for each system so you can extract / query exactly the data you need (in SAP it's mostly SQL but there are a bunch of proprietary "languages" and extensions that can help. In MS it's mostly SQL, in Infor it's worth learning some RPG /CL, but only enough to get the data you need). Learn the notification paradigms each system offers (this can be as simple as scheduling jobs, it can be file-system watchers, it can be RPC based, etc. etc. Each system is different, but you need to know when to do stuff with the data. Both on change from external influences, and on completion of whatever job you ran). Thirdly, utilise a modern language for the "Transform" and "Load" phases of the job. I used to use everything from C, C#, Perl, Python, etc. These languages are much easier and much more powerful than something like RPG or pure SQL for a non-maestro. There are people who use complex stored procedures for everything, and that's cool, but it's also a steeper barrier of entry than using a modern, "batteries-included" language.
The reason I initially taught myself Go (13 years ago now) was due to the incredibly powerful and simple data manipulation packages built into it's standard library. It's a damn good language for doing high speed, low latency transformation of lots of data, while being simple and easy to code and deploy. Having said this, the afore-mentioned C, C#, Perl and Python were all working fine before I switched to Go! Use what you know, and what's available in the sytem you're working on.
If you have any questions feel free to send me an email.
True, but I'm not actually in tech anymore. I still have a consultancy business, but I make money doing geo-technical rope-access work now. A bit of a sea-change.
I'm happy to impart my thoughts on this topic for free, but I'm not sure how useful they would be after almost 10 years!
> Carbon on the other hand appears to be quite a few different components, with many dependencies, some of which are SaaS products, and uses a database (Supabase) which is itself a whole microservice ecosystem that is a considerable effort to deploy
Perhaps this could be addressed by providing a Pulumi or Terraform program?
It's not just about the initial deployment, although these may help. If you're running Wordpress, the question "why is it slow" is pretty limited in scope – you need a faster webserver, database, or maybe need those two to be closer to each other. A simplification but not much of one. For this, is it the app server, the task queue, or one of several other components, or is it in the Supabase layer, or is it a dependency that someone else runs... etc.
Figuring out issues get more complex, scaling gets more complex, backup and recovery get more complex, now you need monitoring for it all too, and with many services the complexity multiplies.
All of that complexity is somewhat justified for a team that exists to build and operate the system (i.e. SaaS), but doesn't really work for a team who exist to build something else and have just been tasked with operating this.
There's also the issue of having a dozen moving parts form the system, each developed for their own reasons. So you could find that upgrading one product changes something, say collation for utf-16, which might be entirely reasonable taken in isolation but that the rest of the system is unprepared for.
It is up to you to fend off dozens of small things. Over time that accumulates. It's like python programmers using two dozen pypi dependencies because they've heard nih is bad. Or think nodejs if that's your thing. What you do in practice is you freeze everything in place and then you postpone it all for an increasingly indefinite future. Organizations then periodically need to freeze work for weeks or even months at a time just to keep up with dependencies. This is clearly a lot of work.
Terraform, or even better Ansible, is a good choice to document make those changes over time in a standardized way. But it doesn't make the work go away. The work is there and still has to be done. Those tools also clearly suffers from the same many-moving-parts problem, as soon as you include external modules with their dependencies too, so you have take care not to magnify the problem by accident instead.
This is what system admins and integrators do all day. They will tell you in unison that the best integration is the one that doesn't exist.
I think we can simplify this over time. Everything in our stack is MIT/Apache. I'm keeping my eye on this fastabase project from Drizzle: https://github.com/drizzle-team/fastabase/tree/main
AGPL so I'd wager the idea is to sell this as a service while still allowing self-hosting, perhaps in the hope to gain bug reports, 'free' testing and some leads.
I’m the owner of a smallish furniture manufacturer. About 15 employees. I built out the order management system myself because nothing really fit our process.
After looking at the site I can’t really say I know how this software could help us. I’ll look at it later on my desktop but first I think some better demo videos or gifs on the landing page would be nice.
When I worked in manufacturing we had an ERP system that was awful, and we ended up supplementing it with Excel spreadsheets and an Access database. I briefly started writing my own ERP system to replace the whole system, but I realized something: my ERP system would be hopelessly tied to our process at this company, and wouldn't be usable by the manufacturer down the street, which my buddy worked at, without extensive rewriting. Software of this kind has a tension between being general-purpose and being really good for one specific workflow.
Maybe ERP is one of those things that co-evolves with the company, shaping the company as much as it's shaped by the company.
This I think will be the future. The ERP I made for my company is hopelessly tied to our process, and it saves time and reduces mental overhead for everyone.
It evolves as we do with me making feature updates and bug fixes every few weeks. Of course this is unusual in that I’m a very technical owner, but I feel this is the right way.
As software becomes easier to make custom software will reduce in price as well. Software gives my company an edge and I’ll take every advantage I can get.
yeah, good point. the docs could definitely use some work. check this out if you're interested. it's not complete, but it goes through the software pretty well: https://learn.carbon.ms
i don't know if you build anything custom, but we do have a configurator
Did you folks roll this yourself? I like the learning platform and was trying to figure out what you've might have used to build it.
thanks, here's the code for it: https://github.com/crbnos/carbon/tree/main/apps/academy
I'll bite. I am a ERP consultant in the SMB manufacturing and distribution space. Primarily we operate on Acumatica, Sage and Netsuite.
The most important thing about ERP systems is - customization. IE: Scripting (netsuite), or even core programming (Sage100 for example). Not just user defined fields but workflows and being able to override and hook into core parts of the system. Say you want to override your cost basis for a certain productline or maybe serve different prices based on the shipping warehouse.
How do you approach that?
EDIT:
How do you handle the finances, G/L auditing, and allt hat financial wizardy?
customers.. they love PDFs. How do you handle generating things like pick lists, invoice sheets, etc? templating?
EDIT2:
One thing big ERPs provide is basically a cohesive way to extend. Not just an API in a RESTFUL sense, it's more akin to an IDE or like GTK+, there's almost everything rolled in for extension inside the 'world view' of the ERP. Every ERP makes some decisions and the rest of the world may flow, be that how you issue credit memos, handle multiple financial entities (do they all have the same chart of accounts? do they all have the same modules? Are there shared users) and so forth. How do you approach that? IE: when you need to slap something like PO's on top of AP, so basically AP + Items and a whole bunch more, does that "flow"? Do you receive those goods and they end up in your inventory for AR? etc.... Having an extensible system is great for addons and consulting, but the bigger piece is - for you, letting your ERP grow and add capabilities.
EDIT3: "Stripe" is not a billing techstack. Mostly CFOs make decisions about billing options, not us lowly tech monkies. Do you support pluggable vaults or anything akin?
these are all excellent questions! i think, interestingly, the answer to all of them is basically -- there's an off the shelf version that's opinionated and good. and if you want to take it a step further, you'd want to just modify the source code.
i think open-source gives consultatnts and integrators super powers that they may not be used to -- everything currently has to be done through abstractions on abstractions. if you can just modify the source code, it becomes a little simpler i think.
take the PDFs for example. just make them how you want them in your instance of the software using the most popular tools on the planet (i don't mean crystal reports): https://github.com/crbnos/carbon/tree/main/packages/document...
I currently work in an ERP adjacent industry serving M&D. I don’t think this is as beneficial as you think it is.
Your value prop lands really well with the Software Architect in me. That part of my skill set loves the idea of creativity, flexibility, etc.
The Director in me does not want that. That sounds like a money pit, never done, management nightmare. What kind of dev do I hire? Do I need a Product Manager for that? How long will it take? Sounds too hard to get a win as a senior leader.
Most of the software in the adjacent space (and ERPs) have “prescriptions” or an ecosystem to get customizations done. Code may get deployed in a special assembly, a special SDK exists, etc
A prescriptive way to get the job done is much more preferred for predictability, even if it is not as loved by the developers.
I think Carbon is a neat and ambitious offering - happy to chat more with you if desired.
The problem with forking is that updating becomes a nightmare. Most ERPs provide a stable-ish API and heavily recommend customers to stick with it, because then automatic updates just work.
I think that's going to be a very hard sell in nearly every scenario. In addition to vendor lock-in you'll then also have people on payroll only to keep your vendor lock-in functional.
i should also say that the accounting is a WIP but modeled on Dynamics 365 - with posting groups, item ledgers, cost ledgers, and general ledgers.