{"id":30091431,"url":"https://github.com/crbnos/carbon","last_synced_at":"2025-12-29T22:05:42.766Z","repository":{"id":308355473,"uuid":"809730532","full_name":"crbnos/carbon","owner":"crbnos","description":"The open-source manufacturing ERP/MES/QMS. Perfect for complex assembly, HMLV, and configure to order manufacturing.","archived":false,"fork":false,"pushed_at":"2025-08-05T12:49:49.000Z","size":25771,"stargazers_count":572,"open_issues_count":30,"forks_count":25,"subscribers_count":4,"default_branch":"main","last_synced_at":"2025-08-05T14:40:04.689Z","etag":null,"topics":["erp","manufacturing","open-source","remix","supabase","typescript"],"latest_commit_sha":null,"homepage":"https://carbon.ms","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/crbnos.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":".github/CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":".github/SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2024-06-03T10:43:24.000Z","updated_at":"2025-08-05T14:39:25.000Z","dependencies_parsed_at":"2025-08-05T14:50:39.629Z","dependency_job_id":null,"html_url":"https://github.com/crbnos/carbon","commit_stats":null,"previous_names":["crbnos/carbon"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/crbnos/carbon","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/crbnos%2Fcarbon","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/crbnos%2Fcarbon/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/crbnos%2Fcarbon/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/crbnos%2Fcarbon/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/crbnos","download_url":"https://codeload.github.com/crbnos/carbon/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/crbnos%2Fcarbon/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":269542974,"owners_count":24435197,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-08-09T02:00:10.424Z","response_time":111,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["erp","manufacturing","open-source","remix","supabase","typescript"],"created_at":"2025-08-09T07:02:52.091Z","updated_at":"2025-12-29T22:05:42.742Z","avatar_url":"https://github.com/crbnos.png","language":"TypeScript","funding_links":[],"categories":["TypeScript"],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n   \u003ca href=\"https://carbon.ms\"\u003e\n      \u003cimg width=\"auto\" height=\"100\" alt=\"Carbon Logo\" src=\"https://github.com/user-attachments/assets/86a5e583-adac-4bf9-8192-508a0adf2308\" /\u003e\n   \u003c/a\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n    The operating system for manufacturing\n    \u003cbr /\u003e\n    \u003cbr /\u003e\n    \u003ca href=\"https://discord.gg/yGUJWhNqzy\"\u003eDiscord\u003c/a\u003e\n    ·\n    \u003ca href=\"https://carbon.ms\"\u003eWebsite\u003c/a\u003e\n    ·\n    \u003ca href=\"https://docs.carbon.ms\"\u003eDocumentation\u003c/a\u003e\n  \u003c/p\u003e\n\u003c/p\u003e\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"https://img.shields.io/badge/Supabase-3ECF8E?style=for-the-badge\u0026logo=supabase\u0026logoColor=white\" alt=\"Supabase\" /\u003e\n  \u003cimg src=\"https://img.shields.io/badge/Typescript-1a67f3?style=for-the-badge\u0026logo=react\u0026logoColor=white\" alt=\"Typescript\" /\u003e\n  \u003cimg src=\"https://img.shields.io/badge/React-23272F?style=for-the-badge\u0026logo=react\u0026logoColor=white\" alt=\"React\" /\u003e\n\u003c/p\u003e\n\n![ERP Screenshot](https://github.com/user-attachments/assets/2e09b891-d5e2-4f68-b924-a1c8ea42d24d)\n\n![MES Screenshot](https://github.com/user-attachments/assets/b04f3644-91aa-4f74-af8d-6f3e12116a6b)\n\n## Does the world need another ERP?\n\nWe built Carbon after years of building end-to-end manufacturing systems with off-the-shelf solutions. We realized that:\n\n- Modern, API-first tooling didn't exist\n- Vendor lock-in bordered on extortion\n- There is no \"perfect ERP\" because each company is unique\n\nWe built Carbon to solve these problems ☝️\n\n## Architecture\n\nCarbon 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](https://github.com/crbnos/carbon/blob/main/examples) folder.\n\n![Carbon Functonality](https://github.com/user-attachments/assets/150c3025-ddcb-4ae4-b7b4-27c670d6cb81)\n\n![Carbon Architecture](https://github.com/user-attachments/assets/3674b2d0-28c7-415f-a8ea-4d8c796337eb)\n\nFeatures:\n\n- [x] ERP\n- [x] MES\n- [x] QMS\n- [x] Custom Fields\n- [x] Nested BoM\n- [x] Traceability\n- [x] MRP\n- [x] Configurator\n- [x] MCP Client/Server\n- [x] API\n- [x] Webhooks\n- [ ] Accounting\n- [ ] Capacity Planning\n- [ ] Simulation\n- [ ] [Full Roadmap](https://github.com/orgs/crbnos/projects/1/views/1)\n\nTechnical highlights:\n\n- [x] Unified auth and permissions across apps\n- [x] Full-stack type safety (Database → UI)\n- [x] Realtime database subscriptions\n- [x] Attribute-based access control (ABAC)\n- [x] Role-based access control (Customer, Supplier, Employee)\n- [x] Row-level security (RLS)\n- [x] Composable user groups\n- [x] Dependency graph for operations\n- [x] Third-party integrations\n\n## Techstack\n\n- [React Router](https://reactrouter.com) – framework\n- [Typescript](https://www.typescriptlang.org/) – language\n- [Tailwind](https://tailwindcss.com) – styling\n- [Radix UI](https://radix-ui.com) - behavior\n- [Supabase](https://supabase.com) - database\n- [Supabase](https://supabase.com) – auth\n- [Upstash](https://upstash.com) - cache\n- [Trigger](https://trigger.dev) - jobs\n- [Resend](https://resend.com) – email\n- [Novu](https://novu.co) – notifications\n- [Vercel](https://vercel.com) – hosting\n- [Stripe](https://stripe.com) - billing\n\n## Codebase\n\nThe monorepo follows the Turborepo convention of grouping packages into one of two folders.\n\n1. `/apps` for applications\n2. `/packages` for shared code\n\n### `/apps`\n\n| Package Name | Description     | Local Command         |\n| ------------ | --------------- | --------------------- |\n| `erp`        | ERP Application | `npm run dev`         |\n| `mes`        | MES             | `npm run dev:mes`     |\n| `academy`    | Academy         | `npm run dev:academy` |\n| `starter`    | Starter         | `npm run dev:starter` |\n\n### `/packages`\n\n| Package Name           | Description                                                             |\n| ---------------------- | ----------------------------------------------------------------------- |\n| `@carbon/database`     | Database schema, migrations and types                                   |\n| `@carbon/documents`    | Transactional PDFs and email templates                                  |\n| `@carbon/ee`           | Integration definitions and configurations                              |\n| `@carbon/jest`         | Jest preset configuration shared across apps and packages               |\n| `@carbon/jobs`         | Background jobs and workers                                             |\n| `@carbon/logger`       | Shared logger used across apps                                          |\n| `@carbon/react`        | Shared web-based UI components                                          |\n| `@carbon/kv`           | Redis cache client                                                      |\n| `@carbon/lib`          | Third-party client libraries (slack, resend)                            |\n| `@carbon/stripe`       | Stripe integration                                                      |\n| `@carbon/tsconfig`     | Shared, extendable tsconfig configuration used across apps and packages |\n| `@carbon/utils`        | Shared utility functions used across apps and packages                  |\n\n## Development\n\n### Setup\n\n1. Clone the repo into a public GitHub repository (or fork https://github.com/crbnos/carbon/fork). If want to make the repo private, you should [acquire a commercial license](https://carbon.ms/sales) to comply with the AGPL license.\n\n   ```sh\n   git clone https://github.com/crbnos/carbon.git\n   ```\n\n2. Go to the project folder\n\n   ```sh\n   cd carbon\n   ```\n\nMake sure that you have [Docker installed](https://docs.docker.com/desktop/install/mac-install/) on your system since this monorepo uses the Docker for local development.\n\nIn addition you must configure the following external services:\n\n| Service     | Purpose                    | URL                                                                    |\n| ----------- | -------------------------- | ---------------------------------------------------------------------- |\n| Upstash     | Serverless Redis           | [https://console.upstash.com/login](https://console.upstash.com/login) |\n| Trigger.dev | Job runner                 | [https://cloud.trigger.dev/login](https://cloud.trigger.dev/login)     |\n| Posthog     | Product analytics platform | [https://us.posthog.com/signup](https://us.posthog.com/signup)         |\n\nEach 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.\n\n### Installation\n\nFirst download and initialize the repository dependencies.\n\n```bash\n$ nvm use           # use node v20\n$ npm install       # install dependencies\n$ npm run db:start  # pull and run the containers\n```\n\nCreate an `.env` file and copy the contents of `.env.example` file into it\n\n```bash\n$ cp ./.env.example ./.env\n```\n\n1. Use the output of `npm run db:start` to set the supabase entries:\n\n- `SUPABASE_SERVICE_ROLE_KEY=[service_role key]`\n- `SUPABASE_ANON_KEY=[anon key]`\n\n2. [Create a Redis database in upstash](https://console.upstash.com/redis) and copy the following from the `REST API` section:\n\n- `UPSTASH_REDIS_REST_URL=[UPSTASH_REDIS_REST_URL]`\n- `UPSTASH_REDIS_REST_TOKEN=[UPSTASH_REDIS_REST_TOKEN]`\n\n3. Navigate to the project you created in [https://cloud.trigger.dev/](Trigger.dev) and copy the following from the `Environments \u0026 API Keys` section:\n\n- `TRIGGER_SECRET_KEY=[Private 'dev' API Key, starting 'tr_dev_*']`\n- `TRIGGER_API_URL=\"https://api.trigger.dev\"`\n- `TRIGGER_PROJECT_ID=[Public 'project' key, starting 'proj*]`\n\n4. In Posthog go to [https://[region].posthog.com/project/[project-id]/settings/project-details](https://[region].posthog.com/project/[project-id]/settings/project-details) to find your Project ID and Project API key:\n\n- `POSTHOG_API_HOST=[https://[region].posthog.com]`\n- `POSTHOG_PROJECT_PUBLIC_KEY=[Project API Key starting 'phc*']`\n\n5. Add a `STRIPE_SECRET_KEY` from the Stripe admin interface, and then run `npm run -w @carbon/stripe register:stripe` to get a `STRIPE_WEBHOOK_SECRET`\n\n- `STRIPE_SECRET_KEY=\"sk_test_*************\"`\n- `STRIPE_WEBHOOK_SECRET=\"whsec_************\"`\n\n6. Signing in requires you to setup one of two methods:\n   - Email requires a Resend API key:\n     - `RESEND_API_KEY=\"re_**********\"`\n     - `RESEND_DOMAIN=\"carbon.ms\"`\n   - Sign-in with Google requires a [Google auth client](https://supabase.com/docs/guides/auth/social-login/auth-google) with these variables:\n     - `SUPABASE_AUTH_EXTERNAL_GOOGLE_CLIENT_ID=\"******.apps.googleusercontent.com\"`\n     - `SUPABASE_AUTH_EXTERNAL_GOOGLE_CLIENT_SECRET=\"GOCSPX-****************\"`\n     - `SUPABASE_AUTH_EXTERNAL_GOOGLE_REDIRECT_URI=\"http://127.0.0.1:54321/auth/v1/callback\"`\n\nThen you can run the following:\n\n```bash\n$ npm run db:build     # run db migrations and seed script\n$ npm run build        # build the packages\n```\n\nFinally, start the apps and packages:\n\n```bash\n$ npm run dev\n$ npm run dev:mes        # npm run dev in all apps \u0026 packages\n```\n\nAfter installation you should be able run the apps locally.\n\n| Application     | URL                                                                                                                |\n| --------------- | ------------------------------------------------------------------------------------------------------------------ |\n| ERP             | [http://localhost:3000](http://localhost:3000)                                                                     |\n| MES             | [http://localhost:3001](http://localhost:3001)                                                                     |\n| Academy         | [http://localhost:4111](http://localhost:4111)                                                                     |\n| Starter         | [http://localhost:4000](http://localhost:4000)                                                                     |\n| Postgres        | [postgresql://postgres:postgres@localhost:54322/postgres](postgresql://postgres:postgres@localhost:54322/postgres) |\n| Supabase Studio | [http://localhost:54323/project/default](http://localhost:54323/project/default)                                   |\n| Mailpit         | [http://localhost:54324](http://localhost:54324)                                                                   |\n| Edge Functions  | [http://localhost:54321/functions/v1/\u003cfunction-name\u003e](http://localhost:54321/functions/v1/\u003cfunction-name\u003e)         |\n\n\n### Code Formatting\n\nThis project uses [Biome](https://biomejs.dev/) for code formatting and linting. To set up automatic formatting on save in VS Code:\n\n1. Install the [Biome VS Code extension](https://marketplace.visualstudio.com/items?itemName=biomejs.biome)\n\n2. Add the following to your VS Code settings (`.vscode/settings.json` or global settings):\n\n```json\n\"editor.codeActionsOnSave\": {\n  \"source.organizeImports.biome\": \"explicit\",\n  \"source.fixAll.biome\": \"explicit\"\n},\n\"editor.defaultFormatter\": \"biomejs.biome\"\n```\n\n### Commands\n\nTo add an edge function\n\n```bash\n$ npm run db:function:new \u003cname\u003e\n```\n\nTo add a database migration\n\n```bash\n$ npm run db:migrate:new \u003cname\u003e\n```\n\nTo add an AI agent\n\n```bash\n$ npm run agent:new \u003cname\u003e\n```\n\nTo add an AI tool\n\n```bash\n$ npm run tool:new \u003cname\u003e\n```\n\nTo kill the database containers in a non-recoverable way, you can run:\n\n```bash\n$ npm run db:kill   # stop and delete all database containers\n```\n\nTo restart and reseed the database, you can run:\n\n```bash\n$ npm run db:build # runs db:kill, db:start, and setup\n```\n\nTo run a particular application, use the `-w workspace` flag.\n\nFor example, to run test command in the `@carbon/react` package you can run:\n\n```\n$ npm run test -w @carbon/react\n```\n\nTo restore a production database locally:\n\n1. Download the production database as a .backup file\n2. Rename the `migrations` folder to `_migrations`\n3. Restore the database with the following command:\n\n```bash\n$ npm run db:build # this should error out at the seed step\n$ PGPASSWORD=postgres psql -h localhost -p 54322 -U supabase_admin -d postgres \u003c ~/Downloads/db_cluster-17-11-2025@09-03-36.backup\n$ npm run dev\n```\n\n4. Rename the `_migraitons` folder back to `migrations`\n\n## API\n\nThe API documentation is located in the ERP app at `${ERP}/x/api/js/intro`. It is auto-generated based on changes to the database.\n\nThere are two ways to use the API:\n\n1. From another codebase using a supabase client library:\n\n- [Javascript](https://supabase.com/docs/reference/javascript/introduction)\n- [Flutter](https://supabase.com/docs/reference/dart/introduction)\n- [Python](https://supabase.com/docs/reference/python/introduction)\n- [C#](https://supabase.com/docs/reference/csharp/introduction)\n- [Swift](https://supabase.com/docs/reference/swift/introduction)\n- [Kotlin](https://supabase.com/docs/reference/kotlin/introduction)\n\n2. From within the codebase using our packages.\n\n### From another Codebase\n\nFirst, set up the necessary credentials in environment variables. For the example below:\n\n1. Navigate to settings in the ERP to generate an API key. Set this in `CARBON_API_KEY`\n2. Get the Supabase URL to call (this is `SUPABASE_URL` in your `.env` if hosting locally, e.g. http://localhost:54321). Set this as `CARBON_API_URL`.\n3. Get the `SUPABASE_ANON_KEY` e.g. from your .env file. Set this as `CARBON_PUBLIC_KEY`.\n\nIf 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 need to include the `carbon-key` header.\n\n```ts\nimport { Database } from \"@carbon/database\";\nimport { createClient } from \"@supabase/supabase-js\";\n\nconst apiKey = process.env.CARBON_API_KEY;\nconst apiUrl = process.env.CARBON_API_URL;\nconst publicKey = process.env.CARBON_PUBLIC_KEY;\n\nconst carbon = createClient\u003cDatabase\u003e(apiUrl, publicKey, {\n  global: {\n    headers: {\n      \"carbon-key\": apiKey,\n    },\n  },\n});\n\n// returns items from the company associated with the api key\nconst { data, error } = await carbon.from(\"item\").select(\"*\");\n```\n\n### From the Monorepo\n\n```tsx\nimport { getCarbonServiceRole } from \"@carbon/auth\";\nconst carbon = getCarbonServiceRole();\n\n// returns all items across companies\nconst { data, error } = await carbon.from(\"item\").select(\"*\");\n\n// returns items from a specific company\nconst companyId = \"xyz\";\nconst { data, error } = await carbon\n  .from(\"item\")\n  .select(\"*\")\n  .eq(\"companyId\", companyId);\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcrbnos%2Fcarbon","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcrbnos%2Fcarbon","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcrbnos%2Fcarbon/lists"}