---
source_hash: "42bed795"
title: "Debug and Logs"
weight: 120
---

# Debug and Logs

SmartCommon provides a colored logging system to facilitate debugging your application.

## Enable Debug Mode

In the Provider configuration:

```javascript
const config = {
  debug: true, // Enable logs globally
  api: {
    debug: true // Enable API-specific logs
  }
};
```

In development, use the environment variable:

```javascript
const config = {
  debug: import.meta.env.DEV // true in dev, false in prod
};
```

## Log Utility

SmartCommon exports a `log` utility with colored methods:

```javascript
import { log } from '@cap-rel/smartcommon';

// State logs
log.state('State change:', newState);
log.globalState('Global state updated:', globalState);

// Lifecycle logs
log.effect('useEffect triggered');
log.page('Page loaded: /dashboard');

// Status logs
log.success('Operation successful');
log.error('An error occurred:', error);
log.warning('Warning:', message);
log.info('Information:', data);

// API logs
log.apiLoading('GET', '/api/items');
log.apiSuccess('GET - 200', '/api/items');
log.apiError('GET - 404', '/api/items');

// Database logs
log.db('INSERT:', item);

// Location logs
log.location('Navigating to:', path);

// Custom log
log.custom('MY_TAG', 'purple', 'My message', data);
```

## Log Colors

Each log type has a distinct color in the console:

| Method | Color | Usage |
| --- | --- | --- |
| `log.state` | Blue | Local state changes |
| `log.globalState` | Dark Cyan | Global state changes |
| `log.effect` | Purple | React effects (useEffect) |
| `log.page` | Orange | Page loading |
| `log.success` | Green | Successful operations |
| `log.error` | Red | Errors |
| `log.warning` | Gold | Warnings |
| `log.info` | Gray | Information |
| `log.apiLoading` | Gray | API request in progress |
| `log.apiSuccess` | Green | Successful API request |
| `log.apiError` | Red | Failed API request |
| `log.db` | Navy Blue | IndexedDB operations |
| `log.location` | Pink | Navigation |

## createLogger - Logger with Namespace

For more complex projects, `createLogger` allows creating a logger with a dedicated namespace. Logs can be filtered by namespace via `localStorage.LOG_FILTER`.

```javascript
import { createLogger } from '@cap-rel/smartcommon';

const logger = createLogger('MyModule');

logger.info('Module initialized');
logger.success('Data loaded');
logger.error('Load failed');
logger.warning('Data outdated');
logger.state('Local change:', newState);
logger.globalState('Global change:', data);
logger.effect('useEffect triggered');
logger.page('/dashboard');
logger.db('INSERT', item);

// API (first parameter = dynamic label)
logger.apiLoading('GET /items');
logger.apiSuccess('GET /items', data);
logger.apiError('GET /items', error);

// Custom
logger.custom('PERF', 'orange', 'Rendered in 12ms');

// Groups
logger.group('Initialization');
logger.info('Step 1');
logger.info('Step 2');
logger.groupEnd();
```

### Filter by Namespace

In the browser console:

```javascript
localStorage.LOG_FILTER = 'MyModule,Auth';  // Show only these namespaces
localStorage.LOG_LEVEL = 'warn';            // debug | info | warn | error
```

## DebugConsole - Built-in Console

The `DebugConsole` component displays SmartCommon logs directly in the application (floating FAB `>_` at bottom left, panel with search/filter toolbar, auto-scrolled colored logs).

### Activation

The `DebugConsole` is mounted by the `Provider` **only if the `debug` prop is explicitly passed** (this is NOT triggered by `config.debug`, but by the Provider prop itself):

```javascript
import { Provider } from '@cap-rel/smartcommon';

// Enable only in development mode
<Provider config={config} debug={import.meta.env.DEV}>
  <App />
</Provider>

// Always enable
<Provider config={config} debug>
  <App />
</Provider>
```

The `config.debug` prop remains independent: it controls the verbosity of logs produced by SmartCommon hooks (`useStates`, `useGlobalStates`, `useApi`, etc.), independently from the `DebugConsole` display.

### Props

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `defaultOpen` | boolean | false | Console open on startup |
| `position` | string | "bottom" | Position: "bottom", "top", "left", "right" |
| `height` | string/number | "40vh" | Console height |
| `maxLogs` | number | 500 | Maximum number of logs kept |
| `showFab` | boolean | true | Show floating ">_" button |

### Manual Usage (without Provider)

```javascript
import { DebugConsole } from '@cap-rel/smartcommon';

<DebugConsole defaultOpen={true} position="bottom" maxLogs={200} />
```

The console can be detached into a separate window via the detach button. Logs are shared between windows via `BroadcastChannel`.

## DebugWarnings - Automatic Breakpoints on React Warnings

The `DebugWarnings` component intercepts `console.error` while mounted and triggers `debugger` as soon as a known React warning is emitted. DevTools (Firefox or Chrome) then pause execution at the warning moment, with the full React stack available to identify the faulty component.

When DevTools are closed, `debugger` is a `no-op`: no impact on normal execution.

### Activation

Like `DebugConsole`, `DebugWarnings` is automatically mounted by the `Provider` **when the `debug` prop is passed**:

```javascript
<Provider config={config} debug={import.meta.env.DEV}>
  <App />
</Provider>
```

Inactive in production (when `debug` is `false` / absent). No additional configuration needed in SmartMaker projects.

### Intercepted Warnings

The following patterns trigger an automatic breakpoint:
- `Received NaN for the value attribute` - NaN passed to an `<input>`
- `value prop on input should not be null` - `value={null}` on input
- `changing a controlled input to be uncontrolled` - `value` changes from defined to `undefined`
- `changing an uncontrolled input to be controlled` - reverse
- `Each child in a list should have a unique "key"` - missing `key` in a `.map()`
- `Maximum update depth exceeded` - infinite re-render loop
- `Cannot update a component` - setState during another component's render
- `Warning: Failed prop type` - violated prop-types
- `Warning: React does not recognize` - non-standard prop passed to DOM

### Automatic Diagnosis Before Breakpoint

Before triggering `debugger`, `DebugWarnings` displays an orange `console.group` containing:

- **Raw console.error args**: raw argument array from React (useful if React includes a `componentStack`)
- **React hint**: extraction of "Check the render method of `XXX`" when React mentions it
- **Targeted suspects**: for `value` and `NaN` warnings, list of fibers where `memoizedProps.value` matches the problem, with React owner and `.jsx` source
- **Full form fibers dump** (`console.table`): all `<input>`, `<textarea>`, `<select>` in DOM with their `value`, `type`, `name`, `owner` (parent React component name) and `source` (file:line:col if available)

The dump is built by traversing all fiber roots via `window.__REACT_DEVTOOLS_GLOBAL_HOOK__`. **React DevTools must be installed** in the browser for the fallback to work completely.

In 90% of cases, the `console.table` is enough to visually identify which line has an unexpected value (`undefined`, `NaN`, `null`, inconsistent type).

### Usage with DevTools

- Open DevTools (`F12`)
- Console tab: locate the orange `[DebugWarnings]` block
- Expand the form fibers table -> spot the line with abnormal value -> you have `owner` and `source`
- If you need the React Call Stack: Debugger tab, execution is paused on `debugger` in `DebugWarnings/index.jsx`
- With source maps enabled (see *Vite Configuration for Debug* below), clicking on `source` takes you directly to the `.jsx` file

### Manual Usage

If you want to enable only breakpoints without the `DebugConsole` UI:

```javascript
import { DebugWarnings } from '@cap-rel/smartcommon';

<App>
  {import.meta.env.DEV && <DebugWarnings />}
  ...
</App>
```

Or conversely: `DebugConsole` without breakpoints by mounting it manually instead of using the Provider's `debug` prop.

## Vite Configuration for Debug

SmartCommon's `vite.config.js` (and any SmartMaker project that produces a lib) is configured for two build modes:

```javascript
const shouldMinify = process.env.MINIFY !== "false";

export default defineConfig({
  build: {
    sourcemap: true,            // Always generate source maps
    minify: shouldMinify,       // Minify unless MINIFY=false
    lib: { ... }
  },
  ...
});
```

### Two Modes

| Command | Usage | Dist Size |
| --- | --- | --- |
| `npm run build` | Minified prod build + source map | Normal (~1.2 MB for smartcommon) |
| `MINIFY=false npm run build` | Readable dev build + source map | Larger (~1.7 MB) but original names preserved |

### Why Source Maps

Without source maps, stack traces in Firefox/Chrome display minified names (`FM`, `Nn`, `ee2`...) impossible to interpret.

With source maps:
- Call Stack displays real component names (`Tabbar`, `SignaturePad`, `HomePage`...)
- Clicking a frame takes you directly to the `.jsx` source, exact line
- `DebugWarnings` populates the `source` field in its dumps (file:line:col)
- React DevTools can correctly trace back to application components

**In Firefox**, if you see the message *"Original name mapping is disabled"*, check **"Show original variables"** in the Debugger's Scopes panel.

### Why Non-Minified Mode (MINIFY=false)

Even with source maps, minified code can resist debugging (local variable names compacted, out-of-order reassignments...). The `MINIFY=false` mode keeps all original names in the bundle itself, making the debugger much more readable when setting `breakpoint` in smartcommon source.

**Rule**: use `MINIFY=false` only for local debugging, never for publishing.

## Local Development Workflow with SmartCommon

To iterate quickly on smartcommon without publishing a npm version for each change, use a symlink from the consumer project's `node_modules`.

### Initial Setup

```bash
# In the consumer project (e.g., smartInterventions mobile)
cd ~/dev/myproject/mobile
rm -rf node_modules/@cap-rel/smartcommon
ln -s ~/dev/smartcommon node_modules/@cap-rel/smartcommon
```

The consumer project reads `~/dev/smartcommon/dist/` directly via the symlink.

### Dev Loop

1. Modify source in `~/dev/smartcommon/src/`
2. `cd ~/dev/smartcommon && MINIFY=false npm run build` (4-5 seconds)
3. In consumer project: `rm -rf node_modules/.vite` (purge Vite pre-bundle)
4. Vite automatically reloads on next hit

### Pros / Cons
- **Pros**: no `npm publish`, no registry indexing wait, no version bump for each test
- **Con**: need to purge `.vite/` on each rebuild as Vite pre-bundles `node_modules`

### Back to Normal Mode

To reinstall the registry version:

```bash
rm ~/dev/myproject/mobile/node_modules/@cap-rel/smartcommon
cd ~/dev/myproject/mobile
npm install @cap-rel/smartcommon@<version>
```

## Automatic Logs

When `debug: true` is enabled, SmartCommon automatically logs:

### useStates

```javascript
const st = useStates({
  initialStates: { count: 0 },
  debug: true // Enable logs for this hook
});

st.set('count', 1);
// Console: [STATE] SET count => 1
```

### useGlobalStates

```javascript
const gst = useGlobalStates();
gst.local.set('user', userData);
// Console: [GLOBAL STATE] SET user => {...}
```

### useDb

```javascript
const db = useDb({
  name: 'myApp',
  stores: { items: 'id++' },
  debug: true
});

await db.items.add({ name: 'Item' });
// Console: [DB] CREATE key = 1, item = {...}
```

### useApi

```javascript
// With api.debug: true in config

api.private.get('items');
// Console: [GET - LOADING] https://api.example.com/items
// Console: [GET - 200] https://api.example.com/items
```

## Conditional Debug

Enable debug only for specific hooks:

```javascript
// Global debug disabled
const config = { debug: false };

// But debug enabled for a specific hook
const st = useStates({
  initialStates: { ... },
  debug: true // Override global config
});
```

## Browser Console

SmartCommon logs use CSS styles in the console. To see them correctly:

1. Open DevTools (F12)
2. Go to "Console" tab
3. Ensure "Verbose" filter is enabled

### Filter Logs

In the console, use the filter to show only certain types:
- Type `STATE` to see state logs
- Type `API` to see API logs
- Type `DB` to see database logs

## Best Practices

### Disable in Production

```javascript
const config = {
  debug: import.meta.env.DEV,
  api: {
    debug: import.meta.env.DEV
  }
};
```

### Custom Logs in Your Components

```javascript
import { log } from '@cap-rel/smartcommon';
import { useLibConfig } from '@cap-rel/smartcommon';

const MyComponent = () => {
  const { debug } = useLibConfig();

  const handleClick = () => {
    if (debug) {
      log.custom('MY_COMPONENT', 'teal', 'Button clicked');
    }
    // ...
  };
};
```

### Do Not Log Sensitive Data

```javascript
// Bad
log.info('User logged in:', { password: user.password });

// Good
log.info('User logged in:', { id: user.id, email: user.email });
```

## See Also
- [Configuration](/front/configuration) - Provider Configuration
- [Hooks](/front/hooks) - Hook Documentation
