### Project Setup and Build Commands
Source: https://github.com/wraithyy/attunement/blob/main/CONTRIBUTING.md
Commands to install dependencies, run tests, check types, and build the project. Ensure all commands pass before pushing changes.
```sh
pnpm install
pnpm test # Vitest
pnpm typecheck # tsc --noEmit
pnpm build # tsup → dist
```
--------------------------------
### CLI Documentation Example
Source: https://github.com/wraithyy/attunement/blob/main/_autodocs/configuration.md
Example of generating documentation and piping it to a file.
```bash
attunement docs --schema src/config.ts > CONFIG_SCHEMA.md
```
--------------------------------
### CLI Validation Examples
Source: https://github.com/wraithyy/attunement/blob/main/_autodocs/configuration.md
Basic and advanced usage examples for validating configuration files.
```bash
# Basic validation
attunement check --schema src/config.ts config/prod.json
# With all options
attunement check \
--schema src/config.ts \
--diff \
--strict \
--print-fingerprint \
config/prod.json \
config/staging.json
```
--------------------------------
### HTML injection examples
Source: https://github.com/wraithyy/attunement/blob/main/_autodocs/vite-plugin.md
Demonstrates how configuration is injected into index.html for development and production builds.
```html
```
```html
```
--------------------------------
### Install Attunement
Source: https://github.com/wraithyy/attunement/blob/main/README.md
Add the package to your project using your preferred package manager.
```sh
pnpm add attunement # or npm / yarn
```
--------------------------------
### Basic Vite Plugin Setup
Source: https://github.com/wraithyy/attunement/blob/main/_autodocs/vite-plugin.md
Initializes the plugin with default settings in the Vite configuration file.
```typescript
// vite.config.ts
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";
import { attunement } from "attunement/vite";
export default defineConfig({
plugins: [
react(),
attunement(), // uses defaults
],
});
```
--------------------------------
### Initialize Configuration Loader
Source: https://github.com/wraithyy/attunement/blob/main/_autodocs/core-api.md
Example usage of the attune function with a Zod schema and JSON source.
```typescript
import { z } from "zod";
import { attune, fromJson } from "attunement";
const appConfig = attune({
schema: z.object({
API_URL: z.string(),
LOG_LEVEL: z.enum(["debug", "info", "warn", "error"]).default("warn"),
}),
sources: [fromJson("/app-config.json")],
onLoad: (config) => {
initializeApiClient(config.API_URL);
},
});
// Call before bootstrap
await appConfig.load();
```
--------------------------------
### Common Test Setup Pattern
Source: https://github.com/wraithyy/attunement/blob/main/_autodocs/testing-api.md
Use beforeEach to initialize the TestProvider with specific configuration overrides.
```typescript
// Setup
const testConfig = {
API_URL: "http://localhost:3000",
FEATURE_FLAGS: { darkMode: true },
// defaults for other keys come from schema
};
beforeEach(() => {
const TestProvider = createTestProvider(appConfig, testConfig);
render();
});
```
--------------------------------
### Initialize MSW in main entry
Source: https://github.com/wraithyy/attunement/blob/main/docs/recipes.md
Import the setup module in the main entry point to ensure onReady callbacks execute at boot.
```typescript
// main.tsx
import "./mocks/setup"; // runs onReady callbacks
import { createRoot } from "react-dom/client";
```
--------------------------------
### Migrating from a hand-rolled loader
Source: https://github.com/wraithyy/attunement/blob/main/README.md
Examples showing the transition from manual promise-based configuration loading to the declarative Attunement pattern.
```tsx
// before
fetchConfig().then((config) => {
setApiBaseUrl(config.API_URL);
root.render();
});
```
```tsx
// after: wiring → onLoad, gating → Provider, render is unconditional
export const appConfig = attuneReact({
schema,
sources: [fromJson("/app-config.json")],
onLoad: (config) => setApiBaseUrl(config.API_URL),
});
root.render(
}>
);
```
--------------------------------
### Replace build placeholder via command line
Source: https://github.com/wraithyy/attunement/blob/main/_autodocs/vite-plugin.md
Example command to replace the build placeholder with actual configuration data.
```bash
# Helm/envsubst/sed
sed "s/__ATTUNEMENT_CONFIG__/$(cat config.json | jq -c '.')/g" dist/index.html
```
--------------------------------
### Test Provider Setup Errors
Source: https://github.com/wraithyy/attunement/blob/main/_autodocs/errors.md
Examples of errors triggered by invalid overrides or unsupported async schemas in createTestProvider.
```typescript
createTestProvider(appConfig, {
LOG_LEVEL: "invalid", // not one of enum values
})
// → throws ConfigError with validation issues
```
```typescript
// Schema with async validation
const schema = z.object({...}).parseAsync(...);
createTestProvider(appConfig, {})
// → Error: attunement: async schema validation is not supported in createTestProvider
```
--------------------------------
### AttunedReact Usage Example
Source: https://github.com/wraithyy/attunement/blob/main/_autodocs/react-api.md
Demonstrates wrapping an application with the Provider and consuming configuration via the use hook.
```typescript
// Provider wraps the app tree
}
errorFallback={}
>
// Hook inside tree
function MyComponent() {
const { API_URL } = appConfig.use();
return
API: {API_URL}
;
}
```
--------------------------------
### Accessing Configuration Fingerprint
Source: https://github.com/wraithyy/attunement/blob/main/_autodocs/core-api.md
Example of retrieving and using the configuration fingerprint for tracking.
```typescript
const fp = await appConfig.fingerprint();
console.log(fp.hash); // "a1b2c3d4"
Sentry.setTag("config_version", fp.version ?? fp.hash);
```
--------------------------------
### Imperative Configuration Setup
Source: https://github.com/wraithyy/attunement/blob/main/docs/recipes.md
Initializes global services like loggers or API clients after configuration validation but before the application renders.
```ts
onLoad: (config) => {
setApiBaseUrl(config.API_URL);
initLogger(config.LOG_LEVEL);
},
```
--------------------------------
### Initialize attune configuration
Source: https://github.com/wraithyy/attunement/blob/main/_autodocs/configuration.md
Example usage of the attune function with a Zod schema and a JSON source.
```typescript
const appConfig = attune({
schema: z.object({
API_URL: z.string(),
LOG_LEVEL: z.enum(["debug", "info", "warn", "error"]).default("warn"),
}),
sources: [fromJson("/app-config.json")],
onLoad: (config, fingerprint) => {
initializeApi(config.API_URL);
Sentry.setTag("config", fingerprint.hash);
},
});
```
--------------------------------
### Configuration Overrides
Source: https://github.com/wraithyy/attunement/blob/main/_autodocs/configuration.md
Example of integrating local storage overrides into the application configuration.
```typescript
export const appConfig = attuneReact({
schema,
sources: [
merge(
fromJson("/app-config.json"),
...import.meta.env.DEV ? [fromOverrides()] : [],
),
],
});
```
--------------------------------
### Configure fromJson source
Source: https://github.com/wraithyy/attunement/blob/main/_autodocs/configuration.md
Example of configuring the fromJson source with custom timeout, retry, and header settings.
```typescript
fromJson("/app-config.json", {
timeoutMs: 5000, // faster timeout
retries: 1, // fewer retries
backoffMs: 500, // slower backoff
headers: {
"Authorization": "Bearer token",
"X-Version": "1.0",
},
})
```
--------------------------------
### Register MSW via onReady
Source: https://github.com/wraithyy/attunement/blob/main/docs/recipes.md
Register MSW setup logic using the onReady callback for non-render-critical initialization.
```typescript
// mocks/setup.ts
import { appConfig } from "../config";
appConfig.onReady((config) => {
if (config.USE_MOCKS) {
// Start MSW worker
}
});
```
--------------------------------
### Vite Plugin Configuration
Source: https://github.com/wraithyy/attunement/blob/main/_autodocs/configuration.md
Example of integrating the attunement plugin into the Vite configuration file.
```typescript
// vite.config.ts
import { attunement } from "attunement/vite";
export default defineConfig({
plugins: [
attunement({
configFile: "config/app-config.json",
url: "/runtime-config.json",
injectKey: "__APP_CONFIG__",
buildPlaceholder: `${JSON.stringify({...})}`,
}),
],
});
```
--------------------------------
### Initialize React Configuration
Source: https://github.com/wraithyy/attunement/blob/main/README.md
Define the configuration schema and sources in a module scope to ensure the fetch starts with the application.
```tsx
// config.ts — module scope, so the fetch starts with the app, not with a render
import { z } from "zod";
import { attuneReact, fromJson } from "attunement/react";
import { setApiBaseUrl } from "./api";
export const appConfig = attuneReact({
schema: z.object({
API_URL: z.string(),
LOG_LEVEL: z.enum(["debug", "info", "warn", "error"]).default("warn"),
}),
sources: [fromJson("/app-config.json")],
onLoad: (config) => {
setApiBaseUrl(config.API_URL); // runs before first render
},
});
```
--------------------------------
### fromJson Retry Logic Example
Source: https://github.com/wraithyy/attunement/blob/main/_autodocs/errors.md
Demonstration of the exponential backoff retry behavior for network-related errors.
```text
Attempt 1: fail (timeout 8s) → wait 300ms
Attempt 2: fail (timeout 8s) → wait 600ms
Attempt 3: fail (timeout 8s) → throw error
```
--------------------------------
### Callback Failure Example
Source: https://github.com/wraithyy/attunement/blob/main/_autodocs/errors.md
Example of a callback throwing an error that gets wrapped into a ConfigError.
```typescript
onLoad: (config) => {
throw new Error("initialization failed");
}
// → ConfigError: config callback failed: initialization failed
```
--------------------------------
### Handling ConfigError
Source: https://github.com/wraithyy/attunement/blob/main/_autodocs/core-api.md
Example of catching and processing configuration validation errors.
```typescript
const config = await appConfig.load().catch((error) => {
if (error instanceof ConfigError) {
console.error("Config validation failed:", error.message);
error.issues.forEach((issue) => {
console.error(` ${issue.path?.join(".")}: ${issue.message}`);
});
}
});
```
--------------------------------
### Provider Component Implementation
Source: https://github.com/wraithyy/attunement/blob/main/_autodocs/react-api.md
Example of rendering the Provider with custom fallback, error handling, and error reporting.
```typescript
createRoot(el).render(
Loading config...}
errorFallback={(error, retry) => (
Config failed: {error.message}
)}
onError={(error) => Sentry.captureException(error)}
>
);
```
--------------------------------
### Implement Provider Component
Source: https://github.com/wraithyy/attunement/blob/main/_autodocs/configuration.md
Example usage of the Provider component with fallback and error handling configurations.
```typescript
Loading...}
errorFallback={(error, retry) => (
Config Failed
{error.message}
)}
onError={(error) => logErrorToService(error)}
>
```
--------------------------------
### Dev server middleware behavior
Source: https://github.com/wraithyy/attunement/blob/main/_autodocs/vite-plugin.md
Example of the HTTP responses provided by the dev server middleware.
```http
GET http://localhost:5173/app-config.json
→ 200 + file contents (application/json)
GET http://localhost:5173/app-config.json (file deleted)
→ 404 + "attunement: config/app-config.json not found"
```
--------------------------------
### Config File Missing Error Response
Source: https://github.com/wraithyy/attunement/blob/main/_autodocs/vite-plugin.md
Example of the 404 error returned by the dev server when a configuration file is missing.
```text
GET /app-config.json
← 404 Not Found
← "attunement: config/app-config.json not found"
```
--------------------------------
### attune(options)
Source: https://github.com/wraithyy/attunement/blob/main/_autodocs/core-api.md
Factory function that creates a config loader. Loading starts immediately at module scope; the returned handle caches results across all calls.
```APIDOC
## attune(options)
### Description
Factory function that creates a config loader. Loading starts immediately at module scope; the returned handle caches results across all calls.
### Signature
`function attune(options: AttuneOptions): Attuned, S>`
### Parameters
- **options** (AttuneOptions) - Required - Configuration object containing schema, sources, and optional callbacks
- **options.schema** (StandardSchemaV1) - Required - A Standard Schema (Zod, Valibot, ArkType) defining the config shape and validation
- **options.sources** (Source[]) - Required - Array of source functions tried in order; first non-nullish result wins
- **options.onLoad** ((config: T, fingerprint: Fingerprint) => void | Promise) - Optional - Callback run after validation completes, before load() resolves
### Returns
- **load** (() => Promise) - Method to load the configuration
- **fingerprint** (() => Promise) - Method to retrieve the configuration fingerprint
- **onReady** ((cb: ReadyCallback) => void) - Method to register a callback for when the configuration is ready
### Throws
- **ConfigError** - Thrown if all sources fail or validation fails
### Example
```typescript
import { z } from "zod";
import { attune, fromJson } from "attunement";
const appConfig = attune({
schema: z.object({
API_URL: z.string(),
LOG_LEVEL: z.enum(["debug", "info", "warn", "error"]).default("warn"),
}),
sources: [fromJson("/app-config.json")],
onLoad: (config) => {
initializeApiClient(config.API_URL);
},
});
await appConfig.load();
```
```
--------------------------------
### Devtools Component Usage
Source: https://github.com/wraithyy/attunement/blob/main/_autodocs/configuration.md
Examples of implementing AttunementDevtools with standard and non-zod schemas.
```typescript
```
```typescript
const fields = [
{ key: "API_URL", type: "string", description: "API endpoint" },
{ key: "LOG_LEVEL", type: "enum", values: ["debug", "info", "warn", "error"], description: "" },
];
```
--------------------------------
### GET [url]
Source: https://github.com/wraithyy/attunement/blob/main/_autodocs/vite-plugin.md
The dev server middleware endpoint that serves the configured JSON file.
```APIDOC
## GET [url]
### Description
Serves the configuration file at the specified URL during development.
### Method
GET
### Endpoint
Configured via `options.url` (Default: `/app-config.json`)
### Response
#### Success Response (200)
- **Content** (application/json) - The contents of the configuration file.
#### Error Response (404)
- **Message** - "attunement: [path] not found"
```
--------------------------------
### Configure Attunement Devtools Plugin
Source: https://github.com/wraithyy/attunement/blob/main/_autodocs/devtools-api.md
Example of using the attunementDevtoolsPlugin with custom options like a specific storage key.
```typescript
import { TanStackDevtools } from "@tanstack/react-devtools";
import { attunementDevtoolsPlugin } from "attunement/devtools";
export function App() {
return (
<>
{import.meta.env.DEV && (
)}
>
);
}
```
--------------------------------
### Configure attunement plugin in vite.config.ts
Source: https://github.com/wraithyy/attunement/blob/main/_autodocs/vite-plugin.md
Basic setup for the attunement plugin within a Vite configuration file.
```typescript
// vite.config.ts
import { defineConfig } from "vite";
import { attunement } from "attunement/vite";
export default defineConfig({
plugins: [
attunement({
configFile: "config/app-config.json",
injectKey: "__APP_CONFIG__",
}),
],
});
```
--------------------------------
### Initialize attuneReact
Source: https://github.com/wraithyy/attunement/blob/main/_autodocs/react-api.md
Example usage of attuneReact at module scope for eager loading. Requires React 19+.
```typescript
import { z } from "zod";
import { attuneReact, fromJson } from "attunement/react";
export const appConfig = attuneReact({
schema: z.object({
API_URL: z.string(),
LOG_LEVEL: z.enum(["debug", "info", "warn", "error"]).default("warn"),
}),
sources: [fromJson("/app-config.json")],
onLoad: (config) => initializeApiClient(config.API_URL),
});
```
--------------------------------
### Configuration Validation Error Message
Source: https://github.com/wraithyy/attunement/blob/main/_autodocs/testing-api.md
Example of the error output generated when runtime configuration overrides fail validation.
```text
ConfigError: Invalid runtime config — you didn't say the magic word:
LOG_LEVEL: Invalid enum value. Expected 'debug' | 'info' | 'warn' | 'error' (did you mean "LOG_LEVEL"?)
```
--------------------------------
### Integrate Standalone Widget and TanStack Plugin
Source: https://github.com/wraithyy/attunement/blob/main/_autodocs/devtools-api.md
Example of lazy-loading the Attunement devtools widget and configuring the TanStack plugin within a React application.
```typescript
// App.tsx
import { lazy, Suspense } from "react";
import { TanStackDevtools } from "@tanstack/react-devtools";
import { attunementDevtoolsPlugin } from "attunement/devtools";
import { appConfig } from "./config";
// Lazy load both devtools
const AttunementDevtools = lazy(() =>
import("attunement/devtools").then((m) => ({ default: m.AttunementDevtools }))
);
export function App() {
return (
}
errorFallback={}
>
{import.meta.env.DEV && (
<>
{/* Standalone widget */}
{/* TanStack plugin */}
>
)}
);
}
```
--------------------------------
### Test component configuration with createTestProvider
Source: https://github.com/wraithyy/attunement/blob/main/README.md
Use createTestProvider to inject configuration overrides synchronously during component testing. Overrides are validated against the schema at setup.
```tsx
import { createTestProvider } from "attunement/testing";
import { appConfig } from "./config";
const TestProvider = createTestProvider(appConfig, {
API_URL: "http://localhost:9999", // merged over schema defaults
});
render();
```
--------------------------------
### Validation Failure Example
Source: https://github.com/wraithyy/attunement/blob/main/_autodocs/errors.md
Example of data failing schema validation during configuration loading.
```typescript
// sources return: { API_URL: 123 }
// schema expects: { API_URL: string }
```
--------------------------------
### Invalid Schema Module Example
Source: https://github.com/wraithyy/attunement/blob/main/_autodocs/cli-api.md
An example of a schema module that fails because it imports application-specific code.
```typescript
// src/config-schema.ts — NOT OK for CLI
import { z } from "zod";
import { myHelpers } from "./helpers"; // relative import is OK
import { setupLogger } from "./app"; // ERROR: pulls in app code
export const schema = z.object({...});
```
--------------------------------
### Initialize app config module
Source: https://github.com/wraithyy/attunement/blob/main/_autodocs/vite-plugin.md
Fetch configuration from a remote JSON file using the attuneReact helper.
```typescript
export const appConfig = attuneReact({
schema,
sources: [fromJson("/app-config.json")], // fetches from S3
});
```
--------------------------------
### Bootstrap configuration via URL parameters
Source: https://github.com/wraithyy/attunement/blob/main/_autodocs/devtools-api.md
Pass configuration values directly through the URL query string to override existing settings at runtime.
```text
?config.API_URL=http://localhost:3000&config.LOG_LEVEL=debug
```
--------------------------------
### Project File Structure
Source: https://github.com/wraithyy/attunement/blob/main/CLAUDE.md
Overview of the core source files and configuration files in the repository.
```text
src/index.ts core: attune(), Source, fromJson, fromWindow, ConfigError
src/react.tsx attuneReact(): Provider (Suspense + ConfigBoundary), use()
src/index.test.ts core tests (Vitest)
tsup.config.ts one entry per file = one entry in package.json exports
docs/design.md design pillars, case studies, out of scope
```
--------------------------------
### Development Commands
Source: https://github.com/wraithyy/attunement/blob/main/CLAUDE.md
Standard commands for testing, type checking, and building the project.
```bash
pnpm test # Vitest
pnpm typecheck # tsc --noEmit
pnpm build # tsup → dist (ESM + d.ts)
```
--------------------------------
### Provide Configuration to React App
Source: https://github.com/wraithyy/attunement/blob/main/README.md
Wrap the application with the configuration provider in the main entry point.
```tsx
// main.tsx
createRoot(el).render(
} errorFallback={(error, retry) => }>
);
```
--------------------------------
### Inject config via entrypoint script
Source: https://github.com/wraithyy/attunement/blob/main/_autodocs/vite-plugin.md
Use a shell script to replace placeholders in index.html with JSON configuration.
```bash
# entrypoint.sh
CONFIG_JSON=$(node -e "console.log(JSON.stringify({...}))")
sed "s/__ATTUNEMENT_CONFIG__/$CONFIG_JSON/g" index.html > index.html.tmp
mv index.html.tmp index.html
```
--------------------------------
### Generate schema documentation
Source: https://github.com/wraithyy/attunement/blob/main/_autodocs/README.md
Generate markdown documentation from a configuration schema using the CLI.
```bash
attunement docs --schema src/config.ts > CONFIG.md
```
--------------------------------
### Valid Schema Module Example
Source: https://github.com/wraithyy/attunement/blob/main/_autodocs/cli-api.md
A compliant schema module using Zod for validation and only external imports.
```typescript
// src/config-schema.ts — OK for CLI
import { z } from "zod"; // external only
export const schema = z.object({
API_URL: z.string(),
LOG_LEVEL: z.enum(["debug", "info", "warn", "error"]),
});
```
--------------------------------
### Using the Attuned Interface
Source: https://github.com/wraithyy/attunement/blob/main/_autodocs/core-api.md
Demonstrates loading configuration, accessing fingerprints for telemetry, and registering lifecycle callbacks.
```typescript
const config = await appConfig.load();
console.log(config.API_URL); // fully typed, never undefined
const fp = await appConfig.fingerprint();
Sentry.setTag("config", fp.version ?? fp.hash);
appConfig.onReady((config, fingerprint) => {
// runs before first render (React) or before bootstrap (vanilla)
router.setBasePath(config.BASE_PATH);
});
```
--------------------------------
### CLI Documentation Command
Source: https://github.com/wraithyy/attunement/blob/main/_autodocs/configuration.md
Syntax for generating documentation from a schema.
```bash
attunement docs --schema
```
--------------------------------
### Integrate with Vue provide/inject
Source: https://github.com/wraithyy/attunement/blob/main/docs/recipes.md
Await the configuration load before mounting the application and share the instance using Vue's provide/inject pattern.
```ts
// main.ts
const config = await appConfig.load();
const app = createApp(App);
app.provide(configKey, config);
app.mount("#app");
```
--------------------------------
### Wrap core config with bindReact
Source: https://github.com/wraithyy/attunement/blob/main/_autodocs/react-api.md
Example usage of bindReact for scenarios where the schema is defined in a non-React module.
```typescript
// When schema lives in a React-free module (CLI/app split)
import { attune } from "attunement";
import { bindReact } from "attunement/react";
import { schema } from "./config-schema"; // schema only, no React
const coreConfig = attune({ schema, sources: [fromJson("/app-config.json")] });
export const appConfig = bindReact(coreConfig);
```
--------------------------------
### fromOverrides
Source: https://github.com/wraithyy/attunement/blob/main/_autodocs/configuration.md
Utility to load configuration overrides from localStorage.
```APIDOC
## fromOverrides
### Description
Retrieves configuration overrides stored in localStorage.
### Parameters
- **storageKey** (string) - Optional - localStorage key for overrides (default: "attunement:overrides")
### Example
```typescript
fromOverrides("my_key")
```
```
--------------------------------
### fromJson(url, options?)
Source: https://github.com/wraithyy/attunement/blob/main/_autodocs/configuration.md
Configures a JSON source for fetching configuration data from a URL.
```APIDOC
## fromJson(url, options?)
### Description
Fetches configuration data from a specified URL with configurable retry and timeout settings.
### Parameters
- **url** (string) - Required - Absolute or relative URL to fetch.
- **timeoutMs** (number) - Optional - Per-attempt timeout in milliseconds (default: 8000).
- **retries** (number) - Optional - Extra attempts after first (default: 2).
- **backoffMs** (number) - Optional - Base backoff in milliseconds (default: 300).
- **cache** (string) - Optional - Fetch cache policy (default: "no-store").
- **headers** (object) - Optional - Request headers.
- **credentials** (string) - Optional - Credentials mode (default: "same-origin").
- **signal** (AbortSignal) - Optional - Abort controller signal.
```
--------------------------------
### Generate schema documentation with attunement docs
Source: https://github.com/wraithyy/attunement/blob/main/_autodocs/cli-api.md
Generates a markdown table representing schema fields, types, and defaults.
```bash
attunement docs --schema
```
```bash
attunement docs --schema src/config.ts > CONFIG.md
```
--------------------------------
### Configuring Multiple Overrides
Source: https://github.com/wraithyy/attunement/blob/main/_autodocs/testing-api.md
Shows how to provide multiple configuration overrides simultaneously when creating a test provider.
```typescript
const TestProvider = createTestProvider(appConfig, {
API_URL: "http://localhost:9999",
LOG_LEVEL: "debug",
FEATURE_FLAGS: { betaUI: true },
THEME: "dark",
});
```
--------------------------------
### fromOverrides(storageKey?)
Source: https://github.com/wraithyy/attunement/blob/main/_autodocs/devtools-api.md
Creates a source that loads configuration overrides from localStorage and URL parameters. This function is intended for development use to dynamically adjust application settings.
```APIDOC
## fromOverrides(storageKey?)
### Description
Loads configuration overrides from localStorage and URL parameters. Overrides are merged with existing configuration and validated against the schema.
### Signature
`function fromOverrides(storageKey?: string): Source`
### Parameters
- **storageKey** (string) - Optional - The localStorage key used for persisting overrides. Defaults to "attunement:overrides".
### Returns
- **Source** - A source function to be used in the attunement configuration pipeline.
### Usage Example
```typescript
import { fromOverrides } from "attunement/devtools";
import { merge, fromJson, attuneReact } from "attunement/react";
const devOverrides = import.meta.env.DEV ? [fromOverrides()] : [];
export const appConfig = attuneReact({
schema,
sources: [merge(fromJson("/app-config.json"), ...devOverrides)],
onLoad: (config) => initializeApi(config.API_URL),
});
```
### URL Bootstrap
Overrides can be passed via URL query parameters using the `config.` prefix:
`?config.API_URL=http://localhost:3000&config.LOG_LEVEL=debug`
```
--------------------------------
### fromWindow(key)
Source: https://github.com/wraithyy/attunement/blob/main/README.md
Retrieves configuration from a global window object, requiring zero network requests.
```APIDOC
## fromWindow(key)
### Description
Retrieves configuration from a global window object, requiring zero network requests.
```
--------------------------------
### Configure onReady wiring
Source: https://github.com/wraithyy/attunement/blob/main/docs/recipes.md
Use onReady in external modules to register callbacks during initial load. Ensure these modules are statically imported in the main entry file.
```ts
// router.ts — imported by main.tsx, not by config.ts
import { appConfig } from "./config";
appConfig.onReady((config) => {
router.update({ context: { apiUrl: config.API_URL } });
});
```
--------------------------------
### attunement(options: AttunementViteOptions)
Source: https://github.com/wraithyy/attunement/blob/main/_autodocs/vite-plugin.md
Initializes the Attunement Vite plugin with configuration options.
```APIDOC
## attunement(options: AttunementViteOptions)
### Description
Initializes the plugin within the Vite configuration to serve application configuration files.
### Parameters
- **configFile** (string) - Optional - Path to the configuration file.
- **url** (string) - Optional - The URL endpoint where the config is served.
- **injectKey** (string | false) - Optional - The key used for window injection, or false to disable.
- **buildPlaceholder** (string) - Optional - Placeholder string used during build time.
```
--------------------------------
### Invalid JSON Error Response
Source: https://github.com/wraithyy/attunement/blob/main/_autodocs/vite-plugin.md
Example of the 500 error returned by the dev server when the configuration file contains invalid JSON.
```text
GET /app-config.json
← 500
```
--------------------------------
### Initialize Non-React Configuration
Source: https://github.com/wraithyy/attunement/blob/main/README.md
Use the core library to load configuration in non-React environments by awaiting the load method.
```ts
import { attune, fromJson } from "attunement";
export const appConfig = attune({ schema, sources: [fromJson("/app-config.json")] });
await appConfig.load(); // typed, validated, cached
```
--------------------------------
### Initialize Attunement with Standard Schema
Source: https://github.com/wraithyy/attunement/blob/main/_autodocs/README.md
Demonstrates how to use Zod, Valibot, or ArkType schemas with the attune function.
```typescript
import { z } from "zod";
import { v } from "valibot";
import { type } from "arktype";
// All work the same
const schema1 = z.object({...});
const schema2 = v.object({...});
const schema3 = type({...});
const appConfig = attune({ schema: schema1, sources: [...] });
```
--------------------------------
### Runtime Configuration Fetching
Source: https://github.com/wraithyy/attunement/blob/main/_autodocs/vite-plugin.md
Fetches the configuration from a JSON file at runtime.
```typescript
// src/config.ts
export const appConfig = attuneReact({
schema,
sources: [fromJson("/app-config.json")],
});
```
--------------------------------
### Create an independent kill switch configuration
Source: https://github.com/wraithyy/attunement/blob/main/docs/recipes.md
Define a secondary configuration instance for emergency shutdowns by reading a separate JSON file at boot.
```ts
export const shutdownConfig = attune({
schema: z.object({ SHUTDOWN: z.boolean().default(false) }),
sources: [fromJson("/shutdown.json", { retries: 0 })],
});
```
--------------------------------
### Organize schema and configuration files
Source: https://github.com/wraithyy/attunement/blob/main/README.md
Split configuration into a schema-only file, a core handle, and optional React bindings to maintain clean dependencies.
```ts
// src/config-schema.ts — schema only, zero imports except zod
import { z } from "zod";
export const schema = z.object({
API_URL: z.string(),
LOG_LEVEL: z.enum(["debug", "info", "warn", "error"]),
});
// src/config.ts — core handle, same module scope as main.tsx/cli.ts
import { attune } from "attunement";
import { schema } from "./config-schema";
export const appConfig = attune({ schema, sources: [fromJson("/app-config.json")] });
// src/config.react.tsx — React bindings (you don't need this yet)
import { bindReact } from "attunement/react";
import { appConfig } from "./config";
export const AppConfig = bindReact(appConfig); // independent context if multiple bindings needed
```
--------------------------------
### Handle optional configuration overrides
Source: https://github.com/wraithyy/attunement/blob/main/docs/recipes.md
Wrap a source in a helper function to treat 404 errors as empty configurations instead of merge failures.
```typescript
const optional = (source: Source): Source => () =>
Promise.resolve(source()).catch(() => undefined);
merge(fromJson("/config/base.json"), optional(fromJson("/config/env.json")))
```
--------------------------------
### writeOverrides(overrides, storageKey?)
Source: https://github.com/wraithyy/attunement/blob/main/_autodocs/devtools-api.md
Writes configuration overrides to localStorage.
```APIDOC
## writeOverrides(overrides, storageKey?)
### Description
Writes the provided overrides object to localStorage. This function silently fails if in private mode or if the storage quota is exceeded.
### Signature
`function writeOverrides(overrides: Record, storageKey?: string): void`
### Parameters
- **overrides** (Record) - Required - The configuration overrides to save.
- **storageKey** (string) - Optional - The key used to access localStorage.
```
--------------------------------
### Configuring Error Boundaries
Source: https://github.com/wraithyy/attunement/blob/main/_autodocs/react-api.md
Demonstrates how to use errorFallback within the Provider to catch configuration-specific errors while allowing app-level errors to bubble up.
```jsx
}>
{/* Render errors here bubble to a higher boundary */}
}>
{/* Catches app render errors */}
```
--------------------------------
### makeFingerprint(config, raw)
Source: https://github.com/wraithyy/attunement/blob/main/_autodocs/core-api.md
Computes a fingerprint from the loaded configuration and raw input.
```APIDOC
## makeFingerprint(config, raw)
### Description
Computes a fingerprint from loaded config and raw input. Exported for CLI fingerprinting.
### Signature
`function makeFingerprint(config: unknown, raw: unknown): Fingerprint`
```
--------------------------------
### Validate configuration files with attunement check
Source: https://github.com/wraithyy/attunement/blob/main/_autodocs/cli-api.md
Use the check command to validate JSON files against a schema, detect environment drift, or enforce strict secret hygiene.
```bash
attunement check --schema [--diff] [--strict] [--print-fingerprint]
```
```bash
# Basic validation
attunement check --schema src/config.ts config/prod.json config/staging.json
# With drift detection and fingerprints
attunement check --schema src/config.ts --diff --print-fingerprint config/*.json
# Strict secret hygiene (fail on credential-like keys)
attunement check --schema src/config.ts --strict config/*.json
```
--------------------------------
### optional(source)
Source: https://github.com/wraithyy/attunement/blob/main/_autodocs/core-api.md
Wraps a configuration source to ensure that any failures result in skipping the source rather than failing the entire chain.
```APIDOC
## optional(source)
### Description
Wraps a source so that failures (synchronous throws or promise rejections) are treated as 'skip this source' instead of causing the chain to fail. This is useful for optional configuration files or environment-specific overrides.
### Signature
`function optional(source: Source): Source`
### Parameters
- **source** (`Source`) - Required - The source to make optional.
### Returns
- A `Source` function that returns `undefined` on any error.
```
--------------------------------
### Use Window Injection Source
Source: https://github.com/wraithyy/attunement/blob/main/README.md
Add the window source to the configuration sources to enable zero-request injection.
```tsx
// config.ts
import { fromWindow, fromJson } from "attunement/react";
export const appConfig = attuneReact({
schema,
sources: [
fromWindow("__APP_CONFIG__"), // dev/staging: window global, zero request
fromJson("/app-config.json"), // fallback: fetch from static file
],
onLoad: (config) => { /* ... */ },
});
```
--------------------------------
### Run Single Test File
Source: https://github.com/wraithyy/attunement/blob/main/CONTRIBUTING.md
Execute a specific test file using Vitest.
```sh
pnpm vitest run src/index.test.ts
```
--------------------------------
### Defining a Custom Source
Source: https://github.com/wraithyy/attunement/blob/main/_autodocs/core-api.md
Shows the Source type signature and an implementation for retrieving configuration from localStorage.
```typescript
type Source = () => unknown;
```
```typescript
// Custom source: localStorage
const fromLocalStorage: Source = () =>
localStorage.getItem("config")
? JSON.parse(localStorage.getItem("config")!)
: undefined;
const appConfig = attune({
schema,
sources: [fromLocalStorage, fromJson("/fallback.json")],
});
```
--------------------------------
### attunement(options?)
Source: https://github.com/wraithyy/attunement/blob/main/_autodocs/configuration.md
Configures the Attunement Vite plugin with options for file paths, injection keys, and build placeholders.
```APIDOC
## attunement(options?)
### Description
Initializes the Attunement plugin for Vite. It accepts an optional configuration object to define how the application configuration is loaded and injected.
### Parameters
- **configFile** (string) - Optional - Path to config file relative to root. Default: "config/app-config.json"
- **url** (string) - Optional - URL served in dev. Default: "/app-config.json"
- **injectKey** (string | false) - Optional - Window global for injection; false disables. Default: false
- **buildPlaceholder** (string) - Optional - JS placeholder for builds. Default: "__ATTUNEMENT_CONFIG__"
### Usage Example
```typescript
import { attunement } from "attunement/vite";
export default defineConfig({
plugins: [
attunement({
configFile: "config/app-config.json",
url: "/runtime-config.json",
injectKey: "__APP_CONFIG__",
buildPlaceholder: "__CONFIG__"
}),
],
});
```
```
--------------------------------
### Integration with Vitest and React Testing Library
Source: https://github.com/wraithyy/attunement/blob/main/_autodocs/testing-api.md
Uses beforeEach to initialize a fresh TestProvider for each test case within a Vitest suite.
```typescript
import { describe, it, expect, beforeEach } from "vitest";
import { render, screen } from "@testing-library/react";
import { createTestProvider } from "attunement/testing";
import { appConfig } from "./config";
describe("MyComponent", () => {
let TestProvider;
beforeEach(() => {
TestProvider = createTestProvider(appConfig, {
API_URL: "http://test:3000",
});
});
it("uses test config", () => {
render();
const { API_URL } = appConfig.use();
expect(API_URL).toBe("http://test:3000");
});
});
```
--------------------------------
### Load configuration without guarantees
Source: https://github.com/wraithyy/attunement/blob/main/docs/recipes.md
Use the load promise to execute logic after the first render if the before-first-render guarantee is not required.
```ts
// auth.ts — fires after first render is OK
appConfig.load().then((config) => {
userManager = new UserManager({ authority: config.OAUTH_AUTHORITY });
});
```
--------------------------------
### Accessing config fingerprint
Source: https://github.com/wraithyy/attunement/blob/main/README.md
Demonstrates how to access the configuration hash and version metadata within the onLoad callback.
```ts
onLoad: (config, { hash, version }) => {
Sentry.setTag("config", version ?? hash);
},
```
--------------------------------
### use() Hook
Source: https://github.com/wraithyy/attunement/blob/main/_autodocs/react-api.md
Provides synchronous access to validated, fully-typed configuration. Must be used within a Provider component.
```APIDOC
## use()
### Description
Synchronous access to validated, fully-typed config. Only valid inside .
### Signature
function use(): T
### Returns
Validated config object (same type as load() promise).
### Throws
- Error if called outside context
```
--------------------------------
### Custom Plugin Configuration Paths
Source: https://github.com/wraithyy/attunement/blob/main/_autodocs/vite-plugin.md
Defines custom paths, URLs, and placeholders for the configuration injection process.
```typescript
// vite.config.ts
export default defineConfig({
plugins: [
react(),
attunement({
configFile: "src/runtime-config.json", // anywhere in root
url: "/api/config", // any path
injectKey: "__RUNTIME__", // any key name
buildPlaceholder: '"__REPLACE_ME__"', // custom placeholder
}),
],
});
```
--------------------------------
### Configure onLoad wiring
Source: https://github.com/wraithyy/attunement/blob/main/docs/recipes.md
Use onLoad within the config module to execute logic before the first render.
```ts
// config.ts
export const appConfig = attuneReact({
schema,
sources: [...],
onLoad: (config) => {
setApiBaseUrl(config.API_URL); // run before first render
},
});
```
--------------------------------
### Configure Vite Plugin for Injection
Source: https://github.com/wraithyy/attunement/blob/main/README.md
Set up the Vite plugin to inject configuration into the window object during development.
```ts
// vite.config.ts
import { attunement } from "attunement/vite";
export default defineConfig({
plugins: [
attunement({
configFile: "config/app-config.json",
injectKey: "__APP_CONFIG__", // injects into window at dev, placeholder for deploy
}),
],
});
```
--------------------------------
### attunement docs
Source: https://github.com/wraithyy/attunement/blob/main/_autodocs/cli-api.md
Generates a markdown table of schema fields, types, defaults, and descriptions.
```APIDOC
## CLI Command: attunement docs
### Description
Generates a markdown table of schema fields, types, defaults, and descriptions based on the provided schema module.
### Usage
`attunement docs --schema `
### Options
- **--schema** (string) - Required - Path to module exporting the schema.
```
--------------------------------
### Config Module with Injection Support
Source: https://github.com/wraithyy/attunement/blob/main/_autodocs/vite-plugin.md
Uses the injected window key as a primary source with a fallback to the JSON file.
```typescript
// src/config.ts
import { fromWindow, fromJson } from "attunement/react";
export const appConfig = attuneReact({
schema,
sources: [
fromWindow("__APP_CONFIG__"), // zero-request in dev
fromJson("/app-config.json"), // fallback for prod or if window missed
],
});
```
--------------------------------
### attunement docs
Source: https://github.com/wraithyy/attunement/blob/main/_autodocs/configuration.md
Generates documentation from a schema module.
```APIDOC
## attunement docs
### Description
Generates documentation based on the provided schema module.
### Parameters
- **--schema** (string) - Required - Module path exporting schema
### Example
```bash
attunement docs --schema src/config.ts > CONFIG_SCHEMA.md
```
```
--------------------------------
### Make a source optional
Source: https://github.com/wraithyy/attunement/blob/main/_autodocs/core-api.md
Wraps a source to suppress errors, returning undefined instead of failing the chain. Useful for optional configuration files.
```typescript
const appConfig = attune({
schema,
sources: [
fromJson("/app-config.json"),
optional(fromJson("/environment.json")), // 404 OK, try next
],
});
```
--------------------------------
### Basic Component Test with Attunement
Source: https://github.com/wraithyy/attunement/blob/main/_autodocs/testing-api.md
Demonstrates wrapping a component in a TestProvider to inject configuration values during testing.
```typescript
import { render, screen } from "@testing-library/react";
import { createTestProvider } from "attunement/testing";
import { appConfig } from "./app-config";
import { Dashboard } from "./Dashboard";
describe("Dashboard", () => {
const TestProvider = createTestProvider(appConfig, {
API_URL: "http://localhost:9999",
});
it("displays the API URL", () => {
render(
);
expect(screen.getByText(/localhost:9999/)).toBeInTheDocument();
});
});
```
--------------------------------
### createTestProvider(config, overrides?)
Source: https://github.com/wraithyy/attunement/blob/main/_autodocs/testing-api.md
Creates a synchronous Provider for tests that injects validated configuration directly into the React context.
```APIDOC
## createTestProvider(config, overrides?)
### Description
Creates a synchronous Provider for tests that injects validated config directly into the context. This allows components to consume configuration without triggering network requests or Suspense fallbacks.
### Parameters
- **config** (AttunedReact) - Required - App config handle (from attuneReact()).
- **overrides** (Partial) - Optional - Values merged over schema defaults; validated against schema.
### Returns
- **Provider** (Function) - A synchronous React component that provides the configuration to its children.
### Throws
- **ConfigError** - If overrides fail validation.
- **Error** - If the schema is async (async validation is not supported in tests).
### Example
```typescript
import { render } from "@testing-library/react";
import { createTestProvider } from "attunement/testing";
import { appConfig } from "./config";
const TestProvider = createTestProvider(appConfig, {
API_URL: "http://localhost:9999",
});
render(
);
```
--------------------------------
### Validate configuration in CI
Source: https://github.com/wraithyy/attunement/blob/main/_autodocs/README.md
Use the CLI to validate configuration files against a defined schema during continuous integration.
```bash
attunement check --schema src/config.ts config/*.json
```
--------------------------------
### Configure MSW with attuneReact
Source: https://github.com/wraithyy/attunement/blob/main/docs/recipes.md
Use the onLoad hook to conditionally initialize MSW based on the USE_MOCKS configuration flag.
```typescript
// config.ts
export const appConfig = attuneReact({
schema: z.object({
API_URL: z.string(),
USE_MOCKS: z.boolean().default(import.meta.env.DEV),
}),
sources: [...],
onLoad: (config) => {
if (config.USE_MOCKS) {
// MSW setup fires at module scope after config loads
void import("./mocks/handlers").then((m) => {
// start MSW worker
});
}
},
});
```
--------------------------------
### Lazy Loading Pattern for AttunementDevtools
Source: https://github.com/wraithyy/attunement/blob/main/_autodocs/devtools-api.md
Demonstrates the correct dynamic import pattern versus the incorrect static import pattern that would include the component in production builds.
```typescript
// ✅ Correct: static import wrapped in dynamic boundary
const AttunementDevtools = lazy(() =>
import("attunement/devtools").then((m) => ({ default: m.AttunementDevtools }))
);
// ❌ Wrong: static import shipped to production
import { AttunementDevtools } from "attunement/devtools";
if (import.meta.env.DEV) {
// AttunementDevtools bundle already included ^^
}
```
--------------------------------
### Validate configuration in GitHub Actions
Source: https://github.com/wraithyy/attunement/blob/main/docs/recipes.md
Integrate Attunement into a CI pipeline to ensure configuration files match the defined schema on every push.
```yaml
# .github/workflows/ci.yml
config-check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 24
- run: npm ci
- run: npx attunement check --schema src/config-schema.ts config/*.json --diff
```
--------------------------------
### readOverrides(storageKey?)
Source: https://github.com/wraithyy/attunement/blob/main/_autodocs/devtools-api.md
Reads configuration overrides from localStorage.
```APIDOC
## readOverrides(storageKey?)
### Description
Reads overrides from localStorage for the specified storage key.
### Signature
`function readOverrides(storageKey?: string): Record`
### Parameters
- **storageKey** (string) - Optional - The key used to access localStorage.
### Returns
- **Record** - Parsed overrides object, or {} if invalid/missing.
```
--------------------------------
### Generate Changeset
Source: https://github.com/wraithyy/attunement/blob/main/CONTRIBUTING.md
Create a new changeset file to track user-facing changes for release automation.
```sh
pnpm changeset
```
--------------------------------
### Inject Environment Variables into Config
Source: https://github.com/wraithyy/attunement/blob/main/docs/recipes.md
Methods for replacing placeholders in a template configuration file using shell utilities or infrastructure-as-code.
```bash
# Using envsubst (Kubernetes, docker entrypoint, CI)
export API_URL=https://api.prod.example.com
export LOG_LEVEL=warn
envsubst < /app/config.template.json > /app/config.json
```
```bash
# Using sed (shell only)
sed -e "s|__API_URL__|https://api.prod.example.com|g" \
-e "s|__LOG_LEVEL__|warn|g" \
/app/config.template.json > /app/config.json
```
```hcl
# Using Terraform + null_resource
locals {
config_values = {
API_URL = var.api_url
LOG_LEVEL = "warn"
}
}
resource "null_resource" "config" {
provisioners "local-exec" {
command = "envsubst < config.template.json > config.json"
environment = {
API_URL = local.config_values.API_URL
LOG_LEVEL = local.config_values.LOG_LEVEL
}
}
}
```
--------------------------------
### diffKeys(files)
Source: https://github.com/wraithyy/attunement/blob/main/_autodocs/cli-api.md
Finds keys present in some files but missing in others to detect environment drift.
```APIDOC
## diffKeys(files)
### Description
Finds keys present in some files but missing in others (environment drift). Reports the union of all keys across files and identifies which files are missing specific keys.
### Signature
`function diffKeys(files: { file: string; raw: Record }[]): { file: string; key: string }[]`
### Parameters
- **files** (Array) - Required - Array of files with their parsed config objects
- **files[].file** (string) - Required - File name/path
- **files[].raw** (object) - Required - Parsed config object
### Returns
- **Array** (Object) - Array of { file, key } tuples for missing keys
```
--------------------------------
### Integrate with Angular APP_INITIALIZER
Source: https://github.com/wraithyy/attunement/blob/main/docs/recipes.md
Delay application bootstrap until the configuration is resolved using an injection token and the app initializer.
```ts
// config.ts
export const appConfig = attune({ schema, sources: [fromJson("/app-config.json")] });
// app.config.ts
export const CONFIG = new InjectionToken("app-config");
providers: [
provideAppInitializer(() => appConfig.load()),
{ provide: CONFIG, useFactory: () => awaitedConfigValue() },
]
```
--------------------------------
### LocalStorage Format
Source: https://github.com/wraithyy/attunement/blob/main/_autodocs/configuration.md
Expected JSON structure for configuration overrides in localStorage.
```json
{
"API_URL": "http://localhost:3000",
"LOG_LEVEL": "debug"
}
```
--------------------------------
### Create Test Provider
Source: https://github.com/wraithyy/attunement/blob/main/_autodocs/configuration.md
Initializes a test provider with configuration overrides for testing environments.
```typescript
const TestProvider = createTestProvider(appConfig, {
API_URL: "http://localhost:9999",
LOG_LEVEL: "debug",
// other fields use schema defaults
});
```