MainSDK
Search⌘K
How-to

Monorepos

Run several MainSDK apps in one repository with a shared main.workspace.yaml, one main.lock, and mainsdk check only on what a change touches.

Planned for 0.7

Status Status is where the work is: Planned (in a milestone, not started), Building (tickets in progress), Preview (usable, may change), then the stability it ships at.

Stability The promise an interface ships with.

  • Stable Follows semantic versioning; breaking changes need a new major, 12 months of overlap and a codemod.
  • Beta Usable in production; may change before it becomes stable.
  • Experimental May change or go away; needs an explicit opt-in in main.yaml.
Stability levels
Updated 2026-10-28

Share policies, drivers and overlays across several apps in one repository, and check only what a change touches. Each app keeps its own main.yaml; one optional main.workspace.yaml at the root holds what they share. It is configuration only and adds no runtime code to your bundles.

Before you start: a pnpm, npm or Yarn workspace, or a Turborepo or Nx repo, with at least one app that has a main.yaml.

1. Add the workspace file

text
pinecart/
  main.workspace.yaml     # shared policies, drivers, overlays
  main.lock               # one per workspace
  policies/
  apps/web/main.yaml      # Pinecart web app, Next.js
  apps/api/main.yaml      # Hono API
  packages/ui/
main.workspace.yaml
schema: 1
packages: auto                 # from pnpm, npm or Yarn workspaces, Turborepo or Nx
policies: [policies/]
providers: { email: resend }
overlays: { order: [market, segment, env] }
network: { default: deny, allow: ["*.pinecart.dev"] }
apps/web/main.yaml
schema: 1
project: prj_01JC8Q4W7ZK3M5N8P2R6T9V0XY
baseline: main27
targets: { web: { framework: nextjs } }
auth: { driver: github }

The web app inherits providers.email: resend, the policies and the network list. Packages are discovered from pnpm, npm and Yarn workspaces, Turborepo and Nx. Inheritance runs org, workspace, app, overlays; see main.yaml and overlays.

2. Tighten, never weaken

An app may tighten what the workspace sets. Weakening it needs an exception with an owner and an expiry.

apps/api/main.yaml
network: { default: allow }    # weakens the workspace
exceptions:
  - rule: net.default_deny
    reason: Partner VPN gateway until the move to a fixed host
    owner: "@pinecart/platform"
    expires: 2026-11-30

Without the exception, check fails and names the weakened key. An expired exception fails like no exception.

3. Verify where each value comes from

bash
npx mainsdk explain config --package apps/web
snapshot="explain-config-package"
$ npx mainsdk explain config --package apps/web
schema = 1  (apps/web/main.yaml:1)
packages = auto  (main.workspace.yaml:2)
providers.email = resend  (main.workspace.yaml:4)
network.default = deny  (main.workspace.yaml:6)
project = web  (apps/web/main.yaml:2)
auth.driver = github  (apps/web/main.yaml:5)

Each value names the file and line it came from. Add --json for tools.

4. Check only what changed

bash
npx mainsdk check --affected --base origin/develop

--affected checks the packages a change touches, the packages that depend on them, and every app when main.workspace.yaml or main.lock changes. Use --package apps/web for one app or --all for everything. sync takes the same flags.

.github/workflows/mainsdk.yml
name: mainsdk
on: [pull_request]
jobs:
  check:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with: { fetch-depth: 0 }
      - uses: pnpm/action-setup@v4
      - run: pnpm install --frozen-lockfile
      - run: pnpm mainsdk check --affected --base origin/develop

5. Keep one lock for every app

bash
npx mainsdk sync --all

mainsdk sync --all writes one main.lock at the root, so every app resolves the same contract versions, with hashes. No app folder has its own lock.

main.lock
lock: 1
interfaces:
  email: { range: "^1.2", resolved: "1.4.0" }
drivers:
  resend:
    version: 2.3.1
    implements: ["email@^1.2"]
    sha256: "9f2c…"

Org-wide defaults for repos outside this workspace live in main.org.yaml.

Next

Was this page helpful?

↑↓ moveEnter openEsc close

Not decided yet