The open-source operating system for manufacturing
Discord
·
Website
·
Issues
We built Carbon after years of building end-to-end manufacturing systems with off-the-shelf solutions. We realized that:
- Modern, API-first tooling didn't exist
- Vendor lock-in bordered on extortion
- There is no "perfect ERP" because each company is unique
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:
- ERP
- MES
- QMS
- Custom Fields
- Nested BoM
- Traceability
- MRP
- Configurator
- MCP Client/Server
- API
- Webhooks
- Accounting
- Capacity Planning
- Simulation
Technical highlights:
- Unified auth and permissions across apps
- Full-stack type safety (Database → UI)
- Realtime database subscriptions
- Attribute-based access control (ABAC)
- Role-based access control (Customer, Supplier, Employee)
- Row-level security (RLS)
- Composable user groups
- Dependency graph for operations
- Third-party integrations
- Remix – framework
- Typescript – language
- Tailwind – styling
- Radix UI - behavior
- Supabase - database
- Supabase – auth
- Upstash - cache
- Trigger - jobs
- Resend – email
- Novu – notifications
- Vercel – hosting
- Stripe - billing
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 |
-
Clone the repo into a public GitHub repository (or fork https://github.com/crbnos/carbon/fork). If you plan to distribute the code, keep the source code public to comply with AGPLv3. To clone in a private repository, acquire a commercial license
git clone https://github.com/crbnos/carbon.git
-
Go to the project folder
cd carbon
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:
Service | Purpose | URL |
---|---|---|
Upstash | Serverless Redis | https://console.upstash.com/login |
Trigger.dev | Job runner | https://cloud.trigger.dev/login |
Posthog | Product analytics platform | https://us.posthog.com/signup |
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 containers
Create an .env
file and copy the contents of .env.example
file into it
$ cp ./.env.example ./.env
- Use the output of
npm run db:start
to set the supabase entries:
SUPABASE_SERVICE_ROLE_KEY=[service_role key]
SUPABASE_ANON_KEY=[anon key]
- Create a Redis database in upstash and copy the following from the
REST API
section:
UPSTASH_REDIS_REST_URL=[UPSTASH_REDIS_REST_URL]
UPSTASH_REDIS_REST_TOKEN=[UPSTASH_REDIS_REST_TOKEN]
- Navigate to the project you created in https://cloud.trigger.dev/ and copy the following from the
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*']
TRIGGER_PROJECT_ID=[Public 'project' key, starting 'proj*]
- In Posthog go to https://[region].posthog.com/project/[project-id]/settings/project-details to find your Project ID and Project API key:
POSTHOG_API_HOST=[https://[region].posthog.com]
POSTHOG_PROJECT_PUBLIC_KEY=[Project API Key starting 'phc*']
- Add a
STRIPE_SECRET_KEY
from the Stripe admin interface, and then runnpm run -w @carbon/stripe register:stripe
to get aSTRIP_WEBHOOK_SECRET
STRIPE_SECRET_KEY="sk_test_*************"
STRIP_WEBHOOK_SECRET="whsec_************"
- Signing in requires you to setup one of two methods:
- Email requires a Resend API key:
RESEND_API_KEY="re_**********"
RESEND_DOMAIN="carbon.ms"
- Sign-in with Google requires a Google auth client with these variables:
SUPABASE_AUTH_EXTERNAL_GOOGLE_CLIENT_ID="******.apps.googleusercontent.com"
SUPABASE_AUTH_EXTERNAL_GOOGLE_CLIENT_SECRET="GOCSPX-****************"
SUPABASE_AUTH_EXTERNAL_GOOGLE_REDIRECT_URI="http://127.0.0.1:54321/auth/v1/callback"
- Email requires a Resend API key:
Then you can run the following:
$ npm run db:build # run db migrations and seed script
$ npm run build # build the packages
Finally, start the apps and packages:
$ npm run dev
$ npm run dev:mes # npm run dev in all apps & packages
After installation you should be able run the apps locally.
Application | URL |
---|---|
ERP | http://localhost:3000 |
MES | http://localhost:3001 |
Academy | http://localhost:4111 |
Starter | http://localhost:4000 |
Postgres | postgresql://postgres:postgres@localhost:54322/postgres |
Supabase Studio | http://localhost:54323/project/default |
Mailpit | http://localhost:54324 |
Edge Functions | http://localhost:54321/functions/v1/ |
To kill the database containers in a non-recoverable way, you can run:
$ npm run db:kill # stop and delete all database containers
To restart and reseed the database, you can run:
$ npm run db:build # runs db:kill, db:start, and setup
To 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:
- From another codebase using a supabase client library:
- From within the codebase using our packages.
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);