# web-gib - agent-driven ibGib web apps

> [!TIP]
> **🚀 Building Applications with ibgib**:
> Looking to build a downstream web app, browser extension, or UI component on ibgib? Start with the **[Creating IbGib Applications Guide](../../docs/CREATING_IBGIB_APPS_GUIDE.md)** and the **[IbGib Client Applications Developer Guide](../../docs/IBGIB_CLIENT_APPS_GUIDE.md)** for detailed coverage of client bootstrap, Web Components, and remote Hub sync.

:under_construction: _I'm currently in the process of pulling this out as a framework from @ibgib/blank-gib._

This library enables ibgib apps with...

## Build (Monorepo Policy)

> [!IMPORTANT]
> This project is part of a monorepo. Build and development tasks are centralized in the monorepo root via the `@ibgib/build-gib` orchestrator.

### Development & Build
Run these from the monorepo root:
* `npm run build:web-gib` - Performs a full clean and build.
* `npm run test:web-gib` - Runs the full respec-gib test suite for this library.

### Legacy Scripts
Individual package scripts have been streamlined to avoid redundancy. Previous scripts are archived in `docs/ARCHIVE_SCRIPTS.md` at the monorepo root.

* initializing the ibgib environment
  * bootstrapping the metaspace
* utilizing and interacting with IndexedDB
  * IndexedDB-based ibgib space implementation
  * IndexedDB helper functions
* building with the ibgib component framework

## src notes

### *.ext.mts, *.web.mts, *.app.mts

All ibgib code is TypeScript + ES Modules.

* .ext for chrome extension-only (not the app)
* .web.mts - web (not node)
* .app.mts - blank-gib app (not the web extension)

## AI Agent Skills (Scaffolding)

In lieu of a heavy framework CLI, the `@ibgib/web-gib` package comes bundled with built-in agent instructions and templates structure to help your IDE's AI agents natively scaffold new ibgib applications, components, and shells.

Because AI coding assistants typically do not read files inside `node_modules`, you must initialize these skills by copying them directly into your project's root folder. You can do this manually, or we have provided a simple script to do the copying for you.

**Option 1 (For standard projects)**
If `@ibgib/web-gib` is installed at your project root, you can run the executable directly via `npx`:

```bash
npx web-gib-init-agents
```

**Option 2 (For Monorepos & Workspaces)**
If `@ibgib/web-gib` is a dependency on a sub-app (e.g. `apps/my-app`) instead of the workspace root, package manager "hoisting" rules may prevent the executable from appearing at your root level.

To properly initialize the `.agents` folder at your monorepo's root, pull from one of the following commands:

*Choice A (Execute via npx):* Let `npx` automatically resolve and execute the binary hook from the package registry:
```bash
npx -p @ibgib/web-gib web-gib-init-agents
```

*Choice B (Execute script directly):* Bypass the broken `.bin` symlink entirely and execute the raw script locally from within the nested workspace dependency:
```bash
node ./apps/my-app/node_modules/@ibgib/web-gib/tools/init-agents.js
```

**Recommendation for Monorepos:** 
To streamline future updates, it is highly recommended to map whichever execution method you prefer directly into your root `package.json` scripts:

```json
  "scripts": {
    "init-agents": "npx -p @ibgib/web-gib web-gib-init-agents"
  }
```
Or for the direct script approach:
```json
  "scripts": {
    "init-agents": "node ./apps/my-app/node_modules/@ibgib/web-gib/tools/init-agents.js"
  }
```

## Bootstrapping an IbGib App

`@ibgib/web-gib` provides a streamlined, multi-phase bootstrap process that minimizes boilerplate while maximizing performance. A standard ibgib application consists of **8 foundational files**:

1.  `index.html`: The entry point with script tags for `script.mjs` and `index.mjs`.
2.  `script.mts`: **Phase 1**. Immediate UI Shell initialization (e.g., burger menus).
3.  `index.mts`: **Phase 2**. Storage (IndexedDB) and Engine orchestration.
4.  `bootstrap.mts`: **Phase 3**. The heavy ibgib engine and App witness loading.
5.  `constants.mts`: App-specific configuration and UUIDs.
6.  `types.mts`: App-specific global state typing.
7.  `helpers.web.mts`: Environment-aware initialization utilities.
8.  `style.css`: Core application styling.

### Phase 1: Immediate Shell Interactivity (`script.mts`)

To ensure the UI is responsive immediately, the Shell is initialized in a dedicated entry point. This script runs as soon as the HTML is parsed.

```typescript
import { getMyAppShellSvc } from "./ui/shell/my-app-shell-service.mjs";

// Early init of UI Shell logic so the burger menu responds immediately.
getMyAppShellSvc();
```

### Phase 2: Environment Orchestration (`index.mts`)

The `index.mts` file handles the asynchronous setup of storage and triggers the dynamic loading of the heavy ibgib engine.

In your app's entry point (`index.mts`), you should initialize the global namespace immediately, then "spin off" the storage and bootstrap loading to avoid blocking the initial DOM paint.

```typescript
import { 
    initIbGibStorage, 
    initIbGibGlobalThis, 
    dynamicallyLoadBootstrapScript 
} from '@ibgib/web-gib/dist/app-bootstrap/init-orchestration.mjs';

import { APP_CONFIG } from './constants.mjs';
import { simpleIbGibRouterSingleton as router } from './ui/router/router-one-file.mjs';

// 1. Initialize global namespace immediately
initIbGibGlobalThis(APP_CONFIG, 'my_app_key');

/**
 * spin off to avoid forestalling the DOMContentLoaded from firing
 */
async function spinOffStartup(): Promise<void> {
    document.addEventListener('DOMContentLoaded', async () => {
        // 2. Prepare storage (IndexedDB)
        await initIbGibStorage(APP_CONFIG);
        
        // 3. Initialize Router
        router.loadCurrentURLPath();

        // 4. Defer loading the heavy engine
        await dynamicallyLoadBootstrapScript('./bootstrap.mjs', 'bootstrapMyApp');
    });
}

spinOffStartup();
```

### Phase 2: Dynamic Engine Bootstrap (`bootstrap.mts`)

The `bootstrap.mts` file is loaded dynamically. It handles the initialization of the metaspace, identity, and the application witness using a rich set of lifecycle hooks.

```typescript
import { bootstrapIbGibApp } from '@ibgib/web-gib/dist/app-bootstrap/bootstrap.mjs';
import { getIbGibGlobalThis_IbGibApp } from '@ibgib/web-gib/dist/app-bootstrap/init-orchestration.mjs';

import { 
    APP_CONFIG, 
    TAG_AGENT_TEXT, TAG_AGENT_ICON, TAG_AGENT_DESCRIPTION,
    MY_APP_SPACE_PREFIX
} from './constants.mjs';
import { MyAppApp_V1 } from './witness/app/my-app-app-v1.mjs';
import { PARAM_INFOS } from './witness/app/my-app-constants.mjs';
import { DEFAULT_MY_APP_DATA_V1 } from './witness/app/my-app-types.mjs';
import { registerAgentFunctionInfos } from './api/function-infos.web.mjs';

export async function bootstrapMyApp() {
    await bootstrapIbGibApp({
        config: APP_CONFIG,
        // Bridge function that provides the typed globalThis for your app
        getGlobalThis: (config) => getIbGibGlobalThis_IbGibApp('my_app_key', config),
        AppClass: MyAppApp_V1,
        defaultAppData: DEFAULT_MY_APP_DATA_V1,
        paramInfos: PARAM_INFOS,
        // Lifecycle hooks
        registerAgentFunctionInfos,
        ensureTags: [
            { text: TAG_AGENT_TEXT, icon: TAG_AGENT_ICON, description: TAG_AGENT_DESCRIPTION }
        ],
        localSpaceNamePrefix: MY_APP_SPACE_PREFIX,
        onReady: async (app) => {
            console.log('Engine ready!');
            // Initialize your UI shell service here
            // getAppShellSvc().onEngineReady();
        }
    });
}
```

## UI Architecture: Custom @ibgib component framework

For details on the Web Component-based reactive UI framework, how to create components, and how to use the built-in validation APIs for form handling, see the dedicated [Custom Component Documentation](file:///c:/Users/billm/antigravity/ibgib/libs/web-gib/src/ui/component/README.md).

For internal classes reference and architectural blueprints, see [ARCHITECTURE.md](file:///c:/Users/billm/antigravity/ibgib/libs/web-gib/src/ui/component/ARCHITECTURE.md).

### Local State Isolation & "Coupling" (Local-Only State Relations)

To enable rich local interaction without polluting shared timelines, the framework supports **Coupling**. This mechanism allows local-only state (e.g. settings, local replica configurations, or assigned AI agents) to be associated with a shared, collaborative "domain" `ibgib` without mutating the domain `ibgib` itself.

#### The Problem: Shared vs. Local State
If multiple users share or sync a domain `ibgib` (like a project workspace or a document), mutating it directly to store device-specific preferences (such as window positions, active tabs, or local credential hashes) would change its cryptographic hash and force all other devices to receive those changes.

#### The Solution: Local Mapping Indices
Instead of modifying the domain `ibgib`, we create a separate, local-only "coupled" `ibgib` in the user's local space. We then link them using a local mapping index. The index is itself a special `ibgib` in the local space whose name is derived deterministically from the domain `ibgib` and a specific `scope`.

#### Core Functions

1. **`getIndexNameFromIbGib({ scope, ibGib, ibGibAddr })`**
   * Deterministically generates the name of the special mapping index `ibgib` in the local space.
   * It takes the domain `ibgib`'s primitive ancestor `ib` atom and appends the `scope` suffix:
     `"${ancestorIbOrAtom}_${scope}index"` (e.g., `keystone_settingsindex` or `project_agentindex`).

2. **`coupleDomainIbGibWithLocalIbGibViaIndex({ scope, domainIbGib, localIbGib, metaspace, space })`**
   * Couples a local `ibgib` (the `localIbGib`, e.g. settings or an agent) to a domain `ibgib` (`domainIbGib`).
   * It retrieves or initializes the special index `ibgib` for the given `scope`.
   * It updates the index `ibgib`'s internal `coupleMap` to map the domain `ibgib`'s Time-Joint-Point (TJP) address (its immutable timeline origin) to the coupled `localIbGib`'s current address.

3. **`getLocalCoupledIbGibForDomainIbGib({ scope, ibGib, metaspace, space })`**
   * Retrieves the latest version of the coupled `ibgib` associated with a domain `ibgib`.
   * It locates the special index `ibgib`, extracts the mapped address for the domain `ibgib`'s TJP, resolves its latest evolved address, and returns the retrieved `ibgib`.

#### Framework Applications

* **Component Settings (`IbGibDynamicComponentInstanceBase.initSettings`)**:
  Used to load and couple component-specific settings (e.g., active tabs, expanded panels). The component automatically resolves its settings using `getLocalCoupledIbGibForDomainIbGib` with the component's unique settings scope.
* **Agent Association (`agent-helpers.mts`)**:
  Used to couple a domain `ibgib` (like a conversation or document) to the local AI agent designated to observe or manage its timeline.
