[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"project-73925":3},{"id":4,"name":5,"fullName":6,"owner":7,"repo":5,"description":8,"homepage":9,"htmlUrl":10,"language":11,"languages":10,"totalLinesOfCode":10,"stars":12,"forks":13,"watchers":14,"openIssues":15,"contributorsCount":16,"subscribersCount":16,"size":16,"stars1d":17,"stars7d":18,"stars30d":19,"stars90d":16,"forks30d":16,"starsTrendScore":20,"compositeScore":21,"rankGlobal":10,"rankLanguage":10,"license":22,"archived":23,"fork":23,"defaultBranch":24,"hasWiki":23,"hasPages":23,"topics":25,"createdAt":10,"pushedAt":10,"updatedAt":40,"readmeContent":41,"aiSummary":42,"trendingCount":16,"starSnapshotCount":16,"syncStatus":43,"lastSyncTime":44,"discoverSource":45},73925,"carbon","crbnos\u002Fcarbon","crbnos","Carbon is an open source ERP, MES and QMS for manufacturing. Perfect for complex assembly, contract manufacturing, and configure to order manufacturing.","https:\u002F\u002Fcarbon.ms",null,"TypeScript",2130,282,17,78,0,3,7,31,9,71.96,"Other",false,"main",[26,27,28,29,30,31,32,33,34,35,36,37,38,39],"agentic-platform","assemblyline","business","erp","lean","management","manufacturing","mcp-server","mes","postgresql","qms","react-router","supabase","typescript","2026-06-12 04:01:12","\u003Cp align=\"center\">\n   \u003Ca href=\"https:\u002F\u002Fcarbon.ms\">\n      \u003Cimg width=\"auto\" height=\"100\" alt=\"Carbon Logo\" src=\"https:\u002F\u002Fgithub.com\u002Fuser-attachments\u002Fassets\u002F86a5e583-adac-4bf9-8192-508a0adf2308\" \u002F>\n   \u003C\u002Fa>\n\u003C\u002Fp>\n\n\u003Cp align=\"center\">\n    The open core for manufacturing\n    \u003Cbr \u002F>\n    \u003Cbr \u002F>\n    \u003Ca href=\"https:\u002F\u002Fdiscord.gg\u002FyGUJWhNqzy\">Discord\u003C\u002Fa>\n    ·\n    \u003Ca href=\"https:\u002F\u002Fcarbon.ms\">Website\u003C\u002Fa>\n    ·\n    \u003Ca href=\"https:\u002F\u002Fdocs.carbon.ms\">Documentation\u003C\u002Fa>\n  \u003C\u002Fp>\n\u003C\u002Fp>\n\u003Cp align=\"center\">\n  \u003Cimg src=\"https:\u002F\u002Fimg.shields.io\u002Fbadge\u002FSupabase-3ECF8E?style=for-the-badge&logo=supabase&logoColor=white\" alt=\"Supabase\" \u002F>\n  \u003Cimg src=\"https:\u002F\u002Fimg.shields.io\u002Fbadge\u002FTypescript-1a67f3?style=for-the-badge&logo=react&logoColor=white\" alt=\"Typescript\" \u002F>\n  \u003Cimg src=\"https:\u002F\u002Fimg.shields.io\u002Fbadge\u002FReact-23272F?style=for-the-badge&logo=react&logoColor=white\" alt=\"React\" \u002F>\n\u003C\u002Fp>\n\n![ERP Screenshot](https:\u002F\u002Fgithub.com\u002Fuser-attachments\u002Fassets\u002F2e09b891-d5e2-4f68-b924-a1c8ea42d24d)\n\n![MES Screenshot](https:\u002F\u002Fgithub.com\u002Fuser-attachments\u002Fassets\u002Fb04f3644-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:\u002F\u002Fgithub.com\u002Fcrbnos\u002Fcarbon\u002Fblob\u002Fmain\u002Fexamples) folder.\n\n![Carbon Functonality](https:\u002F\u002Fgithub.com\u002Fuser-attachments\u002Fassets\u002F150c3025-ddcb-4ae4-b7b4-27c670d6cb81)\n\n![Carbon Architecture](https:\u002F\u002Fgithub.com\u002Fuser-attachments\u002Fassets\u002F3674b2d0-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\u002FServer\n- [x] API\n- [x] Webhooks\n- [ ] Accounting\n- [ ] Capacity Planning\n- [ ] Simulation\n- [ ] [Full Roadmap](https:\u002F\u002Fgithub.com\u002Forgs\u002Fcrbnos\u002Fprojects\u002F1\u002Fviews\u002F1)\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:\u002F\u002Freactrouter.com) – framework\n- [Typescript](https:\u002F\u002Fwww.typescriptlang.org\u002F) – language\n- [Tailwind](https:\u002F\u002Ftailwindcss.com) – styling\n- [Radix UI](https:\u002F\u002Fradix-ui.com) - behavior\n- [Supabase](https:\u002F\u002Fsupabase.com) - database\n- [Supabase](https:\u002F\u002Fsupabase.com) – auth\n- [Redis](https:\u002F\u002Fredis.io) - cache\n- [Inngest](https:\u002F\u002Finngest.com) - jobs\n- [Resend](https:\u002F\u002Fresend.com) – email\n- [Lingui](https:\u002F\u002Flingui.dev) - i18n\n- [Novu](https:\u002F\u002Fnovu.co) – notifications\n- [Vercel](https:\u002F\u002Fvercel.com) – hosting\n- [Stripe](https:\u002F\u002Fstripe.com) - billing\n\n\n## Codebase\n\nThe monorepo follows the Turborepo convention of grouping packages into one of two folders.\n\n1. `\u002Fapps` for applications\n2. `\u002Fpackages` for shared code\n\n### `\u002Fapps`\n\n| Package Name | Description     | How to run                                          |\n| ------------ | --------------- | --------------------------------------------------- |\n| `erp`        | ERP Application | `pnpm dev` (boots stack + ERP via `crbn up` picker) |\n| `mes`        | MES             | `pnpm dev` (select MES in picker, or both)          |\n| `academy`    | Academy         | `pnpm dev:academy`                                  |\n| `starter`    | Starter         | `pnpm dev:starter`                                  |\n\n`pnpm dev` runs the per-worktree dev CLI (`crbn up`). ERP and MES are first-class — the CLI boots the docker stack, applies migrations, regenerates types\u002Fswagger, and spawns the selected apps behind portless. Academy and starter are standalone Turborepo entries.\n\n### `\u002Fpackages`\n\n| Package Name        | Description                                                                |\n| ------------------- | -------------------------------------------------------------------------- |\n| `@carbon\u002Fdatabase`  | Database schema, migrations and types                                      |\n| `@carbon\u002Fdocuments` | Transactional PDFs and email templates                                     |\n| `@carbon\u002Fee`        | Integration definitions and configurations                                 |\n| `@carbon\u002Fconfig`    | Shared configuration (vitest, tsconfig, tailwind) across apps and packages |\n| `@carbon\u002Fjobs`      | Background jobs and workers                                                |\n| `@carbon\u002Flogger`    | Shared logger used across apps                                             |\n| `@carbon\u002Freact`     | Shared web-based UI components                                             |\n| `@carbon\u002Fkv`        | Redis cache client                                                         |\n| `@carbon\u002Flib`       | Third-party client libraries (slack, resend)                               |\n| `@carbon\u002Fstripe`    | Stripe integration                                                         |\n| `@carbon\u002Futils`     | 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:\u002F\u002Fgithub.com\u002Fcrbnos\u002Fcarbon\u002Ffork). If want to make the repo private, you should [acquire a commercial license](https:\u002F\u002Fcarbon.ms\u002Fsales) to comply with the AGPL license.\n\n   ```sh\n   git clone https:\u002F\u002Fgithub.com\u002Fcrbnos\u002Fcarbon.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:\u002F\u002Fdocs.docker.com\u002Fdesktop\u002Finstall\u002Fmac-install\u002F) 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| Posthog | Product analytics platform | [https:\u002F\u002Fus.posthog.com\u002Fsignup](https:\u002F\u002Fus.posthog.com\u002Fsignup) |\n| Stripe | Payments service | [https:\u002F\u002Fdashboard.stripe.com\u002Flogin](https:\u002F\u002Fdashboard.stripe.com\u002Flogin) |\n| Resend | Email service | [https:\u002F\u002Fresend.com](https:\u002F\u002Fresend.com) |\n| Novu | Notifications service | [https:\u002F\u002Fdashboard.novu.co\u002Fauth\u002Fsign-in](https:\u002F\u002Fdashboard.novu.co\u002Fauth\u002Fsign-in) |\n\nPosthog has a free tier which should be plenty to support local development. If you're self hosting and you don't want to use Posthog, it's pretty easy to remove the analytics.\n\n### Installation\n\nFirst download and initialize the repository dependencies.\n\nThis repo uses **pnpm** as its package manager. Enable Corepack so the correct pnpm version (pinned via `packageManager` in `package.json`) is used automatically:\n\n```bash\n$ corepack enable    # one-time: activates pnpm shim from packageManager field\n```\n\nThen install dependencies:\n\n```bash\n$ nvm use            # use node v22\n$ pnpm install       # install dependencies\n```\n\nThe dev stack (Postgres, GoTrue, Kong, Storage, Inngest, Inbucket, Studio, Realtime) is booted later by `crbn up` — see [Local dev CLI](#local-dev-cli-crbn) below. There is no separate \"start the database\" step.\n\n### Local dev CLI (`crbn`)\n\n[![](https:\u002F\u002Fcdn.loom.com\u002Fsessions\u002Fthumbnails\u002F690e6a4ec1c24216b56a22aa2667ba51-ee9275cabb59a0aa-full-play.gif#t=0.1)](https:\u002F\u002Fwww.loom.com\u002Fembed\u002F690e6a4ec1c24216b56a22aa2667ba51)\n\n`crbn` is a small CLI at `packages\u002Fdev\u002Fbin\u002Fcrbn` that wraps two things:\n\n- **Git worktrees** — every feature branch can live in its own checkout dir, so you can switch branches without stashing.\n- **Per-worktree docker compose stack** — each worktree gets its own Postgres \u002F Supabase services on dynamic ports, isolated under `carbon-\u003Cslug>` compose project. Routing is handled by [portless](https:\u002F\u002Fgithub.com\u002Fportless-dev\u002Fportless) (a local HTTPS reverse proxy that serves `*.dev` hostnames on `:443` with locally-trusted certs — installed automatically on first `crbn up`).\n\n> **Windows users:** the dev CLI (`crbn`, `setup.sh`) is POSIX-only and expects **WSL or Git Bash**. Native cmd.exe \u002F PowerShell shells are not supported. From a WSL\u002FGit Bash prompt, the standard flow (`.\u002Fsetup.sh`, `pnpm dev`, `crbn checkout …`) works the same as on macOS\u002FLinux.\n\nRun `setup.sh` once to put `crbn` on your `$PATH` and install the `crbn` shell function (so `crbn checkout` can change cwd):\n\n```bash\n$ .\u002Fsetup.sh                   # writes a sentinel block to ~\u002F.zshrc or ~\u002F.bashrc\n$ source ~\u002F.zshrc              # or open a new shell\n$ crbn                         # shows commands\n```\n\nCommon flows:\n\n```bash\n$ crbn checkout sid\u002Fcool-thing       # cd into worktree (creates if missing,\n                                     # auto-fetches from origin if needed)\n$ crbn checkout -b feat\u002Fnew-thing    # new branch off origin\u002Fmain + worktree\n$ crbn checkout sid\u002Fcool-thing --up  # …and boot the stack inside it\n$ crbn checkout 760                  # fetch GitHub PR #760 into a `pr-760`\n                                     # branch + worktree (fork PRs work too)\n$ crbn copy                          # re-sync .env from main checkout\n$ crbn up | down | reset | status    # per-worktree compose stack\n$ crbn new | list | remove           # interactive worktree management\n```\n\n`crbn up` flags:\n\n- `--no-migrate` — skip `supabase migration up` (use when schema is already current and you just want to re-boot containers fast)\n- `--no-regen` — skip regenerating `packages\u002Fdatabase\u002Fsrc\u002Ftypes.ts` + `swagger-docs-schema.ts` (auto-skipped when `--no-migrate` is set, since no schema change implies no type drift)\n\nFiles synced by `crbn copy` are listed under `package.json#crbn.copy` (defaults to `[\".env\"]`). To uninstall the rc block: `.\u002Fsetup.sh --uninstall`.\n\nCreate an `.env` file and copy the contents of `.env.example` file into it\n\n```bash\n$ cp .\u002F.env.example .\u002F.env\n```\n\n1. **Social Sign In**: Signing in requires you to setup one of two methods:\n\n- Email requires a Resend API key (you'll set this up later on)\n- Sign-in with Google requires a Google auth client with these variables. [See the Supabase docs for instructions on how to set this up](https:\u002F\u002Fsupabase.com\u002Fdocs\u002Fguides\u002Fauth\u002Fsocial-login\u002Fauth-google):\n  - Set `Authorized JavaScript origins` to `https:\u002F\u002Fapi.carbon.dev`\n  - Set `Authorized redirect URIs` to `https:\u002F\u002Fapi.carbon.dev\u002Fauth\u002Fv1\u002Fcallback`\n  - **About the two API URLs you'll see:** each worktree has its own scoped Supabase URL (`https:\u002F\u002F\u003Cworktree>.api.dev`) for app traffic, **and** there is one stable alias `https:\u002F\u002Fapi.carbon.dev` registered on whichever worktree is currently `up`. The stable alias exists only so OAuth callbacks have a single registered redirect URI — one Google Console entry covers every worktree. Day-to-day, your app talks to its worktree-scoped URL; only the OAuth callback hits the stable alias.\n- You should set environment variables like the following.\n  - `SUPABASE_AUTH_EXTERNAL_GOOGLE_CLIENT_ID=\"******.apps.googleusercontent.com\"`\n  - `SUPABASE_AUTH_EXTERNAL_GOOGLE_CLIENT_SECRET=\"GOCSPX-****************\"`\n\n2. **Supabase**: Backend services run inside the per-worktree docker stack — `crbn up` boots them and writes everything you need into `.env.local` automatically:\n\n- `SUPABASE_URL` — portless alias (e.g. `https:\u002F\u002Flocal-dev.api.dev`)\n- `SUPABASE_ANON_KEY`, `SUPABASE_SERVICE_ROLE_KEY` — keys minted per-worktree from a random `SUPABASE_JWT_SECRET`\n- `SUPABASE_DB_URL` — direct Postgres URL on a dynamic port\n\n`.env.local` is generated; do not commit it or hand-edit values that came from `crbn up` (they are re-derived on each boot). Put genuine secrets (OAuth client IDs, Stripe keys, Resend, Novu) in `.env` only.\n\nRun `crbn status` at any time to see the live port assignment and the URLs portless is serving.\n\n3. **Redis** (Caching): No setup needed for local dev — `crbn up` boots a shared Redis container and writes `REDIS_URL` into `.env.local` automatically (each worktree gets its own logical Redis DB). For self-hosted production, set `REDIS_URL` to any Redis-compatible endpoint (Upstash, AWS ElastiCache, etc.) in your prod environment.\n\n4. **Posthog** (Analytics): In Posthog go to [https:\u002F\u002F[region].posthog.com\u002Fproject\u002F[project-id]\u002Fsettings\u002Fproject-details](https:\u002F\u002F[region].posthog.com\u002Fproject\u002F[project-id]\u002Fsettings\u002Fproject-details) to find your Project ID and Project API key:\n\n- `POSTHOG_API_HOST=[https:\u002F\u002F[region].posthog.com]`\n- `POSTHOG_PROJECT_PUBLIC_KEY=[Project API Key starting 'phc*']`\n\n5. **Stripe** (Payment service) - [Create a stripe account](https:\u002F\u002Fdashboard.stripe.com\u002Flogin), add a `STRIPE_SECRET_KEY` from the Stripe `Settings > Developers` interface\n\n- `STRIPE_SECRET_KEY=\"sk_test_*************\"`\n\n6. **Resend** (Email service) - [Create a Resend account](https:\u002F\u002Fresend.com) and configure:\n\n- `RESEND_API_KEY=\"re_**********\"`\n- `RESEND_DOMAIN=\"carbon.ms\"` (or your domain, no trailing slashes or protocols)\n- `RESEND_AUDIENCE_ID=\"*****\"` (Optional - required for contact management in `packages\u002Fjobs`)\n\nResend is used for transactional emails (user invitations, email verification, onboarding). All three variables are stored in `packages\u002Fauth\u002Fsrc\u002Fconfig\u002Fenv.ts`.\n\n7. **Novu** (In-app notifications) - [Create a Novu account](https:\u002F\u002Fdashboard.novu.co\u002Fauth\u002Fsign-in) and configure:\n\n- `NOVU_APPLICATION_ID=\"********************\"` (Client-side, public)\n- `NOVU_SECRET_KEY=\"********************\"` (Server-side secret, backend only)\n\nNovu is used for in-app notifications and notification workflows. After standing up the application and tunnelling port 3000, sync your Novu workflows:\n\n```bash\npnpm run novu:sync\n```\n\nThis command syncs your Novu workflows with the Carbon application using the bridge URL.\n\nFinally, boot the stack and the apps:\n\n```bash\n$ pnpm dev                # equivalent to `crbn up` — picker lets you choose ERP\u002FMES\n```\n\n`crbn up` prints a summary box with the live URLs once the stack is healthy. Defaults look like:\n\n| Surface         | URL                                                            |\n| --------------- | -------------------------------------------------------------- |\n| ERP             | `https:\u002F\u002F\u003Cworktree>.erp.dev`                                   |\n| MES             | `https:\u002F\u002F\u003Cworktree>.mes.dev`                                   |\n| Supabase API    | `https:\u002F\u002F\u003Cworktree>.api.dev`                                   |\n| Supabase Studio | `https:\u002F\u002F\u003Cworktree>.studio.dev`                                |\n| Inngest         | `https:\u002F\u002F\u003Cworktree>.inngest.dev`                               |\n| Mail (Inbucket) | `https:\u002F\u002F\u003Cworktree>.mail.dev`                                  |\n| Postgres        | `postgresql:\u002F\u002Fpostgres:postgres@localhost:\u003CPORT_DB>\u002Fpostgres`  |\n\n`\u003Cworktree>` is derived from the branch name (e.g. `sid-local-dev` → `local-dev`). The main checkout drops the prefix and just uses `erp.dev`, `mes.dev`, etc. Ports for raw TCP services (Postgres, Inbucket, Inngest) are dynamic per-worktree — `crbn status` is the source of truth.\n\nAcademy and starter still run on classic localhost ports via `pnpm dev:academy` \u002F `pnpm dev:starter` (they are not part of the per-worktree stack).\n\n### Code Formatting\n\nThis project uses [Biome](https:\u002F\u002Fbiomejs.dev\u002F) for code formatting and linting. To set up automatic formatting on save in VS Code:\n\n1. Install the [Biome VS Code extension](https:\u002F\u002Fmarketplace.visualstudio.com\u002Fitems?itemName=biomejs.biome)\n\n2. Add the following to your VS Code settings (`.vscode\u002Fsettings.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$ pnpm run db:function:new \u003Cname>\n```\n\nTo add a database migration\n\n```bash\n$ pnpm run db:migrate:new \u003Cname>\n```\n\nTo add an AI agent\n\n```bash\n$ pnpm run agent:new \u003Cname>\n```\n\nTo add an AI tool\n\n```bash\n$ pnpm run tool:new \u003Cname>\n```\n\nTo stop the stack (keeps volumes — data preserved):\n\n```bash\n$ crbn down\n```\n\nTo wipe the stack and start clean (destroys Postgres volume + flushes the redis db for this worktree):\n\n```bash\n$ crbn reset\n```\n\nTo regenerate types or swagger schema manually (normally `crbn up` does this for you after applying migrations):\n\n```bash\n$ pnpm db:types          # → packages\u002Fdatabase\u002Fsrc\u002Ftypes.ts + functions\u002Flib\u002Ftypes.ts\n$ pnpm generate:swagger  # → packages\u002Fdatabase\u002Fsrc\u002Fswagger-docs-schema.ts\n```\n\nTo run a command against a single workspace, use `pnpm --filter`:\n\n```bash\n$ pnpm --filter @carbon\u002Freact test\n```\n\nTo restore a production database snapshot locally:\n\n1. Export a backup from your production Supabase project (`pg_dump` or Supabase Dashboard → Database → Backups).\n2. Boot the stack **without applying migrations** so they don't fight the dump's schema state:\n   ```bash\n   $ crbn up --no-migrate\n   ```\n3. Find the live Postgres port (`crbn status` shows it; or read `PORT_DB` from `.env.local`).\n4. Pipe the backup into the local DB as the superuser (`supabase_admin` for plain-text dumps, or use `pg_restore` for `.dump` archives):\n   ```bash\n   $ source .env.local\n   $ PGPASSWORD=postgres psql -h localhost -p \"$PORT_DB\" -U supabase_admin -d postgres \u003C \u002Fpath\u002Fto\u002Fbackup.sql\n   # …or for .dump archives:\n   $ PGPASSWORD=postgres pg_restore -h localhost -p \"$PORT_DB\" -U supabase_admin -d postgres --no-owner \u002Fpath\u002Fto\u002Fbackup.dump\n   ```\n5. Regenerate types so app code reflects the restored schema:\n   ```bash\n   $ pnpm db:types\n   ```\n\n## API\n\nThe API documentation is located in the ERP app at `${ERP}\u002Fx\u002Fapi\u002Fjs\u002Fintro`. 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:\u002F\u002Fsupabase.com\u002Fdocs\u002Freference\u002Fjavascript\u002Fintroduction)\n- [Flutter](https:\u002F\u002Fsupabase.com\u002Fdocs\u002Freference\u002Fdart\u002Fintroduction)\n- [Python](https:\u002F\u002Fsupabase.com\u002Fdocs\u002Freference\u002Fpython\u002Fintroduction)\n- [C#](https:\u002F\u002Fsupabase.com\u002Fdocs\u002Freference\u002Fcsharp\u002Fintroduction)\n- [Swift](https:\u002F\u002Fsupabase.com\u002Fdocs\u002Freference\u002Fswift\u002Fintroduction)\n- [Kotlin](https:\u002F\u002Fsupabase.com\u002Fdocs\u002Freference\u002Fkotlin\u002Fintroduction)\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:\u002F\u002Flocalhost: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\u002Fdatabase\";\nimport { createClient } from \"@supabase\u002Fsupabase-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>(apiUrl, publicKey, {\n  global: {\n    headers: {\n      \"carbon-key\": apiKey,\n    },\n  },\n});\n\n\u002F\u002F 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\u002Fauth\u002Fclient.server\";\nconst carbon = getCarbonServiceRole();\n\n\u002F\u002F returns all items across companies\nconst { data, error } = await carbon.from(\"item\").select(\"*\");\n\n\u002F\u002F 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\n\n## Translations\n\nIn order to run `pnpm run translate` you must first run:\n\n```bash\nbrew install ollama\nbrew services start ollama\nollama pull llama3.2\ncurl http:\u002F\u002Flocalhost:11434\u002Fapi\u002Ftags\nnpx linguito config set \\\n  llmSettings.provider=ollama \\\n  llmSettings.url=http:\u002F\u002F127.0.0.1:11434\u002Fapi\n```\n## Migration Notes\n\n### Trigger.dev to Inngest\n\nBackground jobs have been migrated from [Trigger.dev](https:\u002F\u002Ftrigger.dev) to [Inngest](https:\u002F\u002Finngest.com). Key changes:\n\n- **Job definitions** moved from `packages\u002Fjobs\u002Ftrigger\u002F` to `packages\u002Fjobs\u002Fsrc\u002Finngest\u002Ffunctions\u002F`\n- **Triggering jobs** from app code uses `trigger()` and `batchTrigger()` from `@carbon\u002Fjobs` instead of `tasks.trigger()` from `@trigger.dev\u002Fsdk`\n- **Inngest dev server** runs via `npx inngest-cli@latest dev -u http:\u002F\u002Flocalhost:3000\u002Fapi\u002Finngest`\n- **Environment variables**: `TRIGGER_SECRET_KEY`, `TRIGGER_API_URL`, and `TRIGGER_PROJECT_ID` are no longer needed. Set `INNGEST_EVENT_KEY` and `INNGEST_SIGNING_KEY` instead (not required for local dev).\n\n### Upstash to Local Redis\n\nThe caching layer (`@carbon\u002Fkv`) no longer depends on Upstash. A standard Redis instance is used instead. The `REDIS_URL` environment variable still applies, but you can point it at any Redis-compatible server (including a local Docker container).\n\n### Supabase CLI to docker compose (`crbn`)\n\nLocal dev no longer relies on `supabase start` \u002F `supabase stop`. The full backend stack (Postgres 15, GoTrue, Kong, Storage, Realtime, Studio, Inngest, Inbucket, edge-runtime) runs from `docker-compose.dev.yml` under a per-worktree compose project (`carbon-\u003Cslug>`), managed by `crbn up` \u002F `down` \u002F `reset`. Ports are allocated dynamically per worktree so multiple branches can run side-by-side. Key changes:\n\n- `pnpm db:start` \u002F `db:stop` \u002F `db:kill` \u002F `db:build` are removed — use `crbn up` \u002F `down` \u002F `reset`.\n- `.env.local` is generated by `crbn up` (worktree-specific URLs, ports, JWT secret, anon\u002Fservice keys). Genuine secrets stay in `.env`.\n- `pnpm db:migrate` now drives `supabase migration up --db-url $SUPABASE_DB_URL`; it falls back to the CLI's linked-project mode when `SUPABASE_DB_URL` is unset.\n- `pnpm db:types` generates types directly from `$SUPABASE_DB_URL` (no `supabase gen types --local`).\n","Carbon 是一个面向制造业的开源ERP、MES和QMS系统，特别适用于复杂装配、合同制造以及按订单配置生产。其核心功能包括物料需求计划（MRP）、质量管理系统（QMS）支持、自定义字段、嵌套物料清单（BOM）管理及追溯性等，采用TypeScript编写，并利用了React、Supabase等现代技术栈以实现全栈类型安全与实时数据库订阅等功能。此外，Carbon设计时考虑到了易于扩展性，允许用户通过API构建自己的应用来满足特定业务需求。该平台非常适合那些寻求灵活、可定制且不希望被单一供应商锁定的中小型制造企业使用。",2,"2026-06-11 03:47:56","high_star"]