Manage Norce Checkout configurations as code. Define configurations in YAML files, preview changes before deploying, and keep configurations in version control.
The Norce Checkout admin UI works well for managing individual channels. As your setup grows, you may find that:
- Multiple channels share settings - Changing API credentials or shared options means updating each channel manually
- Changes are hard to review - No easy way to see what changed, when, or why
- Mistakes are easy to make - A typo in one channel goes unnoticed until something breaks
- Collaboration is tricky - Multiple team members making changes without coordination
nco-control addresses these by treating configurations as code:
- Shared base configurations - Define common settings once, override per-channel
- Review before deploy - See exactly what will change with
ncoctl plan - Version control - Track changes in Git, review in pull requests
# Clone the repository
git clone https://github.com/NorceTech/nco-control.git
cd nco-control
# Install and build
npm install
npm run build
# Link CLI globally (makes 'ncoctl' available)
npm link -w packages/cliVerify the installation:
ncoctl --versionCreate a directory for your merchant's configurations:
mkdir acme-store-checkout
cd acme-store-checkoutCreate ncoctl.config.yaml:
merchant: acme-store
api:
baseUrl: https://acme-store.api-se.stage.norce.tech/checkout/configurationCreate .env with your API token:
NCO_API_TOKEN=your-api-token-hereGetting an API token: Contact Norce support or generate one through the partner portal.
Create adapter configurations as YAML files. For example, walley_checkout_adapter.yaml:
$schema: https://acme-store.api-se.stage.norce.tech/checkout/walley-adapter/openapi/v1/schemas/walley_checkout_adapter.json
id: walley_checkout_adapter
apiSettings:
clientId: "${WALLEY_CLIENT_ID}"
apiSecret: "${WALLEY_API_SECRET}"
options:
discountText:
sv-SE: Rabatt
nb-NO: RabattCreate channel directories with overrides. For example, norway/walley_checkout_adapter.yaml:
id: walley_checkout_adapter
# Each market has its own Walley store
apiSettings:
storeId: "${WALLEY_STORE_ID_NO}"# Validate configurations against schemas
ncoctl validate
# See what would change (local vs remote)
ncoctl plan
# Apply changes (with confirmation)
ncoctl applyExample ncoctl plan output:
Planning changes for acme-store...
sweden/walley_checkout_adapter
~ apiSettings.storeId: "1234" → "5678"
norway/walley_checkout_adapter
(no changes)
Plan: 0 to create, 1 to update, 1 unchanged
A typical configuration project (see samples/acme-store for a working example):
acme-store-checkout/
├── ncoctl.config.yaml # Project settings
├── .env # Secrets (gitignored)
├── norce_adapter.yaml # Shared base configs
├── walley_checkout_adapter.yaml
├── sweden/ # Channel: sweden
│ ├── norce_adapter.yaml
│ └── walley_checkout_adapter.yaml
└── norway/ # Channel: norway
├── norce_adapter.yaml
└── walley_checkout_adapter.yaml
Root-level files are base configurations. Channels inherit from them when they have a matching file with an id field:
# norway/norce_adapter.yaml
id: norce_adapter
# Only specify what differs from root
country:
defaultCountry: "NO"The channel config is deep-merged with the root config. Arrays are replaced, not merged. Use null to explicitly remove an inherited field.
merchant: acme-store
api:
# Partner API URL pattern:
# https://{slug}.api-se.{env}.norce.tech/checkout/configuration
baseUrl: https://acme-store.api-se.stage.norce.tech/checkout/configuration
# Optional settings
schema:
# cacheDir: .ncoctl/schemas # Schema cache location
# cacheTtl: 86400 # Cache TTL in seconds (24h default)
# skip: false # Skip schema validation
output:
# format: text # Output format: text or json
# verbose: false # Show unchanged configs| Variable | Description |
|---|---|
NCO_API_TOKEN |
Bearer token for Configuration API |
Set via environment variable or .env file in project root.
# Required for plan/apply
NCO_API_TOKEN=your-api-token-here
# Adapter secrets - referenced as ${VAR_NAME} in YAML
WALLEY_STORE_ID_SE=your-sweden-store-id
WALLEY_STORE_ID_NO=your-norway-store-id
WALLEY_CLIENT_ID=your-client-id
WALLEY_API_SECRET=your-api-secret
NORCE_IDENTITY_SECRET=your-secretncoctl validate # Validate all configs
ncoctl validate --channel sweden # Validate specific channel
ncoctl plan # Preview all changes
ncoctl plan --channel sweden # Preview specific channel
ncoctl plan --json # Output as JSON
ncoctl apply # Apply changes (prompts for confirmation)
ncoctl apply --yes # Apply without confirmation
ncoctl apply --channel sweden # Apply specific channel- CLI (
ncoctl) - Implemented and in use - Web interface - Planned
- Motivation - Use cases and design philosophy
- Architecture - Technical design
- Tech Stack - Technology choices
- API - Configuration API reference
npm install # Install dependencies
npm run build # Build all packages
npm run dev # Watch mode
npm test # Run tests
npm run lint # Lint code
npm run format # Format with Prettier| Component | Technology |
|---|---|
| Language | TypeScript 5.x |
| Runtime | Node.js >= 20 |
| CLI | Commander.js |
| Schema Validation | Ajv |
| YAML | js-yaml |
| Testing | Vitest |
Proprietary - Norce