SlicerX has two layers. The base kit (the slicing engine, settings, viewport, printer connectors, PrintPilot and the MCP server) is MPL-2.0 and can be embedded anywhere; docs/embedding.md covers that. The edition is the full product built on the base: accounts, cloud slicing, the free model library with creator pages, the branded desktop, web and phone apps, and the site. The edition is AGPL-3.0-or-later.
To ship your own edition (a print farm's customer app, a printer maker's slicer, a school's lab tool), you do not edit the code. You write one configuration file, and every edition surface reads it: the web and desktop apps, the phone app, the site, the cloud service and sx-link.
Status: the schema, loaders and build helpers are in packages/edition-config. The apps are switching to them now; until that lands, some surfaces still use built-in values.
What the configuration covers
| Section | What it sets |
|---|---|
id |
a short machine id (harbor), used in file names, storage keys and user agents |
brand |
product name, short name, tagline, logo files, theme (nocturne or token overrides on it), support email |
apps |
web origin, desktop identifier and product name, iOS bundle id and team id, Android application id and signing fingerprints, the deep link scheme, universal link domains |
backend |
Supabase URL and anon key, the cloud API, the relay for phone pairing, the local sx-link port |
features |
store, feed, creators, cloudSlicing, phonePairing, pilot, demoData, and each printer family (bambu, moonraker, prusalink, octoprint, duet, creality, elegoo, snapmaker, spoolman, homeassistant) |
auth |
sign-in providers (email, github, google, apple, discord) with their public client ids |
ai |
PrintPilot's provider (openai, anthropic, openai-compatible, none), default model, base URL, and where the key comes from (keychain, env, cloud) |
legal |
terms, privacy and imprint links, the source link for your builds, a trademark notice |
Everything you leave out comes from neutral defaults: a plain reference slicer with PrintPilot and every printer family on, and no store, cloud or phone features. The JSON Schema is packages/edition-config/schema/edition-config.schema.json, so editors can complete and check the file for you.
Worked example: Harbor Slice
Harbor Print Co. (a fictional print service) wants a slicer for its customers. Customers sign in, buy prints of Harbor's catalog, and slice in Harbor's cloud; there is no creator feed and no phone pairing. Harbor runs its own model behind an OpenAI-compatible endpoint, and its customers do not use Duet, Snapmaker or Home Assistant.
harbor.config.ts in Harbor's fork:
import { defineEditionConfig } from '@slicerx/edition-config'
export default defineEditionConfig({
id: 'harbor',
brand: {
name: 'Harbor Slice',
shortName: 'Harbor',
tagline: 'Slicing and print management for Harbor Print Co. customers',
logo: { mark: 'brand/harbor-mark.svg', wordmark: 'brand/harbor-wordmark.svg', appIcon: 'brand/harbor-icon.png' },
theme: { base: 'nocturne', tokens: { colors: { purple: '#4fb3bf', pink: '#f2a65a' }, fonts: { display: 'Space Grotesk' } } },
supportEmail: 'support@harborprint.example',
},
apps: {
web: { origin: 'https://slice.harborprint.example' },
desktop: { identifier: 'com.harborprint.slice', productName: 'Harbor Slice' },
ios: { bundleId: 'com.harborprint.slice', teamId: 'ABCDE12345' },
android: { applicationId: 'com.harborprint.slice', sha256CertFingerprints: ['AA:BB:...:99'] },
deepLinkScheme: 'harborslice',
universalLinkDomains: ['slice.harborprint.example'],
},
backend: {
supabase: { url: 'https://abcdefghijklmnop.supabase.co', anonKey: 'public-anon-key-from-the-supabase-dashboard' },
cloudApi: 'https://cloud.harborprint.example',
},
features: {
store: true,
cloudSlicing: true,
printers: { duet: false, snapmaker: false, homeassistant: false },
},
auth: { providers: [{ kind: 'email' }, { kind: 'google', clientId: '1234567890-abc.apps.googleusercontent.com' }] },
ai: { provider: 'openai-compatible', model: 'llama-4-scout', baseUrl: 'https://llm.harborprint.example/v1', keySource: 'cloud' },
legal: {
terms: 'https://harborprint.example/terms',
privacy: 'https://harborprint.example/privacy',
sourceUrl: 'https://git.harborprint.example/harbor-slice/tree/{commit}',
trademarkNotice: 'Harbor Slice is built on SlicerX. SlicerX is a trademark of its owners and is not affiliated with Harbor Print Co.',
},
})The same example as JSON is packages/edition-config/fixtures/fork-harbor.json.
What this gives Harbor:
- The apps say "Harbor Slice" everywhere, use Harbor's logo and colors, and open
harborslice://links and links onslice.harborprint.example. - Sign-in offers email and Google. The store and cloud slicing are on; the Feed and phone pairing never appear.
- PrintPilot talks to Harbor's model through Harbor's cloud, which holds the model key, so no customer needs a key of their own.
- The Printers workspace offers Bambu Lab, Klipper, PrusaLink, OctoPrint, Creality and Elegoo printers and Spoolman, and hides the rest.
- About screens and the site footer link to the exact source of each build.
Check it
node packages/edition-config/src/cli.ts check harbor.config.tsA mistake names the field and the reason:
Invalid edition config:
features.feed: feed needs store
legal.sourceUrl: edition builds are AGPL-3.0: set legal.sourceUrl so users can get the source (section 13)Build it
export SLICERX_CONFIG=$PWD/harbor.config.ts
# web app
pnpm --filter @slicerx/web build
# desktop app (Tauri reads identifiers and deep links from the config)
node packages/edition-config/src/cli.ts tauri harbor.config.ts desktop > harbor.tauri.json
pnpm --filter @slicerx/desktop tauri build --config harbor.tauri.json
# phone app
node packages/edition-config/src/cli.ts tauri harbor.config.ts mobile > harbor.tauri-mobile.json
pnpm --filter @slicerx/mobile tauri ios build --config harbor.tauri-mobile.json
# site, with the files that let the apps open universal links
node packages/edition-config/src/cli.ts well-known harbor.config.ts apps/site/public/.well-known
pnpm --filter @slicerx/site buildAn Expo-based phone app can use expoConfig(config) for the name, slug, scheme, bundle ids, associated domains and Android intent filters. Expo loads app.config.ts synchronously, so run node packages/edition-config/src/cli.ts expo harbor.config.ts and spread the JSON it prints.
Run the services
Services read resolved JSON, which is the config with every default filled in. The Rust services (the cloud service and sx-link) read it through the sx-edition-config crate.
node packages/edition-config/src/cli.ts resolve harbor.config.ts > slicerx.config.json
SLICERX_CONFIG=slicerx.config.json ./cloud-serviceEnvironment overrides
Every loader, in TypeScript and in Rust, applies these on top of the file. They suit values that differ between staging and production.
| Variable | Sets |
|---|---|
SLICERX_CONFIG |
path of the config file (TypeScript or JSON) |
SLICERX_SUPABASE_URL, SLICERX_SUPABASE_ANON_KEY |
backend.supabase |
SLICERX_CLOUD_API_URL |
backend.cloudApi |
SLICERX_RELAY_URL |
backend.relay |
SLICERX_LINK_PORT |
backend.linkPort |
SLICERX_FEATURES |
the enabled features as a comma list (store,cloudSlicing,pilot); replaces the file's toggles |
SLICERX_AI_PROVIDER, SLICERX_AI_MODEL, SLICERX_AI_BASE_URL |
ai |
SLICERX_AUTH_PROVIDERS |
the sign-in providers as a comma list (email,github,google,apple); replaces the file's list |
SLICERX_AUTH_GITHUB_CLIENT_ID, SLICERX_AUTH_GOOGLE_CLIENT_ID, SLICERX_AUTH_APPLE_CLIENT_ID, SLICERX_AUTH_DISCORD_CLIENT_ID |
each provider's public client id; one alone updates that provider in the file's list |
SLICERX_APPLE_TEAM_ID |
apps.ios.teamId, for Sign in with Apple and universal links |
SX_FEATURES is a build-only switch that decides which feature code is compiled in, for example SX_FEATURES= builds with no optional features at all. When it is unset, the configuration decides.
Rules the checker enforces
- Features need what they depend on: the feed needs the store; the store needs Supabase (or
demoData, which serves a bundled demo catalog); cloud slicing needsbackend.cloudApi; phone pairing needs a relay; PrintPilot needs an AI provider, andkeySource: 'cloud'needs the cloud API. - Any build with an edition feature on needs
legal.sourceUrl, because edition code is AGPL-3.0 and users of your apps and site are entitled to its source. - No secrets. The Supabase anon key and OAuth client ids are public by design; the checker refuses a Supabase service role key, API keys (
sk-...) and private keys. Secrets go in your server's environment or a secret manager, and model keys in the OS keychain or your cloud. - Your own name and identity. An edition whose
idis notslicerxcannot use the SlicerX name, the SlicerX logo orapp.slicerx.*identifiers.
Licenses and the name
- Base packages are MPL-2.0. You can combine them with code under any license; changes to our MPL files stay open.
- Edition packages (store, feed, accounts, cloud, the apps and the site) are AGPL-3.0-or-later. If you ship or host a build that includes them, offer your users its complete source;
legal.sourceUrlis where the apps link to it. - Packages under
packages/orcacontain material from OrcaSlicer and are AGPL-3.0-or-later. They are optional. - "SlicerX" and its logo are trademarks. You are free to fork and rebrand; ship under your own name and logo, and say it is built on SlicerX if you like.