Skip to main content
Shipped uses a flexible, file-based configuration system that supports hot-reloading and graceful degradation. Configuration is split into two types: dynamic YAML files and static environment variables.

Configuration Types

Dynamic Configuration

YAML files that update without restart

Static Configuration

Environment variables requiring restart

Dynamic Configuration

Dynamic configuration uses YAML files in your config directory (default: /data/config in Docker). Changes to these files are automatically detected and applied without restarting the container.
FilePurposeReference
lists.yamlDefine which packages to trackLists Guide
providers.yamlConfigure provider defaults and optionsProviders Guide
general.yamlGeneral application settingsGeneral Settings
ui.yamlUI customization optionsUI Customization

File Watching

The config system uses chokidar to monitor file changes:
  • Automatic reload - Changes detected and applied in real-time
  • Debounced processing - Multiple rapid changes are batched
  • Stream-based updates - Connected clients receive updates via SSE
  • Polling mode - Available for Docker/network filesystems
If file watching doesn’t work in your environment (common in Docker on macOS or network filesystems), enable polling mode:
SERVER_CONFIG_WATCH_POLLING=true

Static Configuration

Static configuration uses environment variables and requires a container restart to change. These control server behavior, caching, and system-level settings.
VariableTypeDefaultDescription
SERVER_CONFIG_DIRstringconfigConfig files directory (relative or absolute)
SERVER_CONFIG_WATCH_POLLINGbooleanfalseUse polling for file watching
SERVER_PACKAGES_FETCH_CONCURRENCYinteger10Max parallel package fetches
SERVER_PACKAGES_CACHE_TTLinteger10800Cache TTL in seconds (3 hours)
SERVER_PACKAGES_CACHE_DISABLEDbooleanfalseDisable package caching
See the Environment Variables reference for the complete list.

Graceful Degradation

Shipped’s config system is designed to never crash the app due to user configuration errors:
1

Missing Files

Default config files are created automatically if missing.
2

Parse Errors

Defaults are used and errors are logged. Previous config is retained on reload failures.
3

Invalid Items

Invalid packages or settings are skipped with warnings. The rest of the config remains functional.
4

Schema Validation

Type mismatches use defaults and log warnings without crashing.

Validation and Warnings

Configuration is validated at multiple levels:
  1. YAML parsing - Syntax errors are caught and logged
  2. Effect Schema validation - Runtime type checking with detailed errors
  3. Provider validation - Package-specific validation against provider schemas
  4. View construction - Final validation before use in the application
Warnings are collected during validation and displayed in the UI, helping you identify and fix configuration issues without breaking the application.

IDE Support

Shipped generates JSON schemas for all config files to provide IDE autocompletion and validation.
Add the schema reference to the top of your YAML files:
lists.yaml
# yaml-language-server: $schema: https://raw.githubusercontent.com/nipakke/shipped/main/docs/config-files/lists.json

- name: My Packages
  groups:
    - name: frameworks
      packages:
        - provider: npm
          name: react

Real-Time Updates

By default, Shipped streams configuration changes to all connected clients using Server-Sent Events (SSE) via ORPC.
# Enable/disable real-time config streaming (default: true)
streamConfigChanges: true

How It Works

  1. File Change - chokidar detects a change in a config file
  2. Validation - Config is parsed and validated with Effect Schema
  3. SubscriptionRef Update - Server updates its reactive configuration reference
  4. SSE Broadcast - Change is streamed to all connected clients
  5. Client Update - Clients receive and apply the new configuration
  6. UI Refresh - UI updates automatically without page reload
If streaming is disabled or fails, you can manually refresh configuration:
const { refresh } = useUserConfig();
await refresh();

Configuration Flow

Next Steps

Lists Configuration

Define which packages to track

Providers Configuration

Configure provider-specific options

General Settings

Application-wide settings

UI Customization

Customize the user interface

Build docs developers (and LLMs) love