Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
beb44ec
docs(uikit): add comprehensive UIKit documentation pages
cursoragent Apr 7, 2026
873f1dd
docs(navigation): add UIKit section to Ethereum & EVM sidebar
cursoragent Apr 7, 2026
539de70
docs(uikit): add source code callout linking to GitHub repo
cursoragent Apr 7, 2026
15e4677
docs(uikit): rewrite Mermaid diagrams for clean layout
cursoragent Apr 7, 2026
feac888
docs(uikit): fix capability tiers chart to be readable
cursoragent Apr 7, 2026
b796b8e
docs(uikit): remove legacy reference and consolidate capability tables
cursoragent Apr 7, 2026
9e5a355
docs(uikit): remove multisig from execution strategies diagram
cursoragent Apr 7, 2026
79cacab
docs(uikit): add screenshots from the live example app
cursoragent Apr 7, 2026
fea8f03
docs(uikit): replace broken contract state screenshots with clean ones
cursoragent Apr 7, 2026
d69ecfe
docs(uikit): clean up screenshots — keep only working ones
cursoragent Apr 8, 2026
1afad58
docs(uikit): add ContractStateWidget GIF with side-by-side layout
cursoragent Apr 8, 2026
5b77596
docs(uikit): retake screenshots with fully loaded pages
cursoragent Apr 8, 2026
c98fe77
docs(uikit): remove main screenshot from UIKit index page
cursoragent Apr 8, 2026
4b54197
docs(uikit): replace TransactionForm screenshot with new image
cursoragent Apr 8, 2026
21bf5c2
docs(uikit): replace contract state widget GIF with PNG, fix text ove…
cursoragent Apr 8, 2026
a458a93
docs(uikit): remove old contract-state-widget.gif
cursoragent Apr 8, 2026
63de35b
docs(uikit): update contract state widget PNG with reduced padding
cursoragent Apr 8, 2026
74980f2
docs(uikit): reduce contract state widget image width
cursoragent Apr 8, 2026
4d30d13
docs(uikit): add AddressBookWidget section, dedicated storage page, a…
cursoragent Apr 8, 2026
118a1a2
docs(uikit): remove two-column layout from AddressBookWidget section
cursoragent Apr 8, 2026
956492b
docs(uikit): move AddressBookWidget heading below image
cursoragent Apr 8, 2026
a79642f
docs(uikit): improve provider tree diagram styling
cursoragent Apr 9, 2026
6f97e6d
docs(uikit): fix provider tree diagram text cutoff
cursoragent Apr 9, 2026
d2bd19b
docs(uikit): shorten provider tree diagram labels to fix text cutoff
cursoragent Apr 9, 2026
b511bae
docs(uikit): restore full provider descriptions in Provider Tree diagram
cursoragent Apr 9, 2026
bb49431
docs(uikit): switch Provider Tree to TD layout for readable node text
cursoragent Apr 9, 2026
1d8ef5f
docs(uikit): fix node text truncation with classDef width override
cursoragent Apr 9, 2026
421a37b
docs(uikit): fix incorrect API references in code examples
cursoragent Apr 9, 2026
f3b34b2
docs(uikit): fix cn import — comes from @openzeppelin/ui-utils
cursoragent Apr 9, 2026
51e95fd
docs(uikit): fix useRuntimeContext example — isLoading is inside getR…
cursoragent Apr 9, 2026
71c8536
docs(uikit): add 'Why Use the Storage Plugin' section with real-world…
cursoragent Apr 9, 2026
195b2d9
docs(uikit): add account alias plugin screenshot to storage page
cursoragent Apr 9, 2026
de9d53e
docs(uikit): use side-by-side layout for account alias plugin image
cursoragent Apr 9, 2026
1e2386b
docs(uikit): document React hook factories (createRepositoryHook, cre…
cursoragent Apr 9, 2026
2ad538b
docs(uikit): add missing UI primitives and form field types to Compon…
cursoragent Apr 9, 2026
6c5d935
merge: resolve conflict in react-integration.mdx — keep TD layout fix…
cursoragent Apr 9, 2026
d64d55b
Merge pull request #8 from pasevin/cursor/uikit-storage-why-section-6e41
pasevin Apr 9, 2026
b8d3f8f
Merge pull request #7 from pasevin/cursor/fix-uikit-provider-tree-dia…
pasevin Apr 9, 2026
f3945c6
docs(uikit): fix broken adapter docs links
pasevin Apr 9, 2026
f347a4c
Reorder nav: place UIKit directly below Role Manager
cursoragent Apr 10, 2026
349abe4
Merge pull request #9 from pasevin/cursor/uikit-nav-order-feab
pasevin Apr 10, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
220 changes: 220 additions & 0 deletions content/tools/uikit/architecture.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,220 @@
---
title: Architecture
---

OpenZeppelin UIKit is built as a layered stack of independently installable packages. This page explains how those layers fit together, how the capability-driven adapter model works, and how runtimes manage lifecycle across multiple ecosystems.

## Package Layers

The packages form a dependency chain where each layer builds on the ones below it. Lower layers are lighter and more generic; higher layers add React-specific and domain-specific behavior.

```mermaid
%%{init: {'flowchart': {'nodeSpacing': 20, 'rankSpacing': 40}} }%%
flowchart TD
Storage(["7 · ui-storage"])
Renderer(["6 · ui-renderer"])
ReactPkg(["5 · ui-react"])
Components(["4 · ui-components"])
Styles(["3 · ui-styles"])
Utils(["2 · ui-utils"])
Types(["1 · ui-types"])

Storage --> Utils
Renderer --> Components
ReactPkg --> Components
Components --> Styles
Components --> Utils
Utils --> Types

style Storage fill:#e8eaf6,stroke:#5c6bc0,color:#1a237e
style Renderer fill:#e8eaf6,stroke:#5c6bc0,color:#1a237e
style ReactPkg fill:#e8eaf6,stroke:#5c6bc0,color:#1a237e
style Components fill:#e0f2f1,stroke:#26a69a,color:#004d40
style Styles fill:#e0f2f1,stroke:#26a69a,color:#004d40
style Utils fill:#fff3e0,stroke:#ff9800,color:#e65100
style Types fill:#fff3e0,stroke:#ff9800,color:#e65100
```

**Color key:** <span style={{color: '#5c6bc0'}}>■</span> Application layers (5–7) · <span style={{color: '#26a69a'}}>■</span> UI & design (3–4) · <span style={{color: '#ff9800'}}>■</span> Foundation (1–2)

| Layer | Package | Responsibility |
| --- | --- | --- |
| 1 | `@openzeppelin/ui-types` | TypeScript interfaces for capabilities, schemas, form models, networks, transactions, and execution config. No runtime code — pure type definitions. |
| 2 | `@openzeppelin/ui-utils` | Framework-agnostic helpers: `AppConfigService` for environment/config loading, structured logger, validation utilities, and routing helpers. |
| 3 | `@openzeppelin/ui-styles` | Tailwind CSS 4 theme tokens using OKLCH color space. Ships CSS variables and custom variants (dark mode). No JavaScript. |
| 4 | `@openzeppelin/ui-components` | React UI primitives (buttons, dialogs, cards, tabs) and blockchain-aware form fields (address, amount, bytes, enum, map). Built on Radix UI + shadcn/ui patterns. |
| 5 | `@openzeppelin/ui-react` | `RuntimeProvider` for managing `EcosystemRuntime` instances per network. `WalletStateProvider` for global wallet state. Derived hooks for cross-ecosystem wallet abstraction. |
| 6 | `@openzeppelin/ui-renderer` | `TransactionForm` for schema-driven transaction forms. `ContractStateWidget` for view function queries. `ExecutionConfigDisplay`, `AddressBookWidget`, address book components. |
| 7 | `@openzeppelin/ui-storage` | `EntityStorage` and `KeyValueStorage` base classes on Dexie.js/IndexedDB. Account alias plugin for address-to-name mapping. |

<a id="capabilities"></a>
## Capabilities

The UIKit type system defines 13 **capabilities** — small, focused interfaces that describe what an adapter can do.

Capabilities are organized into three tiers based on their requirements:

```mermaid
%%{init: {'flowchart': {'nodeSpacing': 30, 'rankSpacing': 30}} }%%
flowchart TD
T1["<b>Tier 1 — Lightweight</b><br/>Addressing · Explorer · NetworkCatalog · UiLabels"]
T2["<b>Tier 2 — Network-Aware</b><br/>ContractLoading · Schema · TypeMapping · Query"]
T3["<b>Tier 3 — Stateful</b><br/>Execution · Wallet · UiKit · Relayer · AccessControl"]

T1 --"may import"--> T2 --"may import"--> T3

style T1 fill:#e8eaf6,stroke:#5c6bc0,color:#000
style T2 fill:#e0f2f1,stroke:#26a69a,color:#000
style T3 fill:#fff3e0,stroke:#ff9800,color:#000
```

**Tier 1** requires no runtime context — safe to import anywhere. **Tier 2** needs a `networkConfig`. **Tier 3** additionally needs wallet state and participates in the `dispose()` lifecycle. Each higher tier may import from lower tiers, but never the reverse.

| Capability | Tier | Purpose |
| --- | --- | --- |
| `Addressing` | 1 | Address validation, formatting, checksumming |
| `Explorer` | 1 | Block explorer URL generation |
| `NetworkCatalog` | 1 | Available network listing and metadata |
| `UiLabels` | 1 | Human-readable labels for ecosystem-specific terms |
| `ContractLoading` | 2 | Fetch and parse contract ABIs/IDLs |
| `Schema` | 2 | Transform contract definitions into form-renderable schemas |
| `TypeMapping` | 2 | Map blockchain types (e.g. `uint256`) to form field types |
| `Query` | 2 | Execute read-only contract calls (view functions) |
| `Execution` | 3 | Sign, broadcast, and track transactions |
| `Wallet` | 3 | Connect/disconnect wallets, account state, chain switching |
| `UiKit` | 3 | Ecosystem-specific React components and hooks |
| `Relayer` | 3 | Gas-sponsored transaction execution via relayers |
| `AccessControl` | 3 | Role-based access control queries and snapshots |

For more background on the adapter pattern and how chain-specific integrations are structured, see [Building New Adapters](/ui-builder/building-adapters).

### Capability Bundles

Higher-level components request specific **bundles** of capabilities rather than the full set. For example, `TransactionForm` expects a `TransactionFormCapabilities` type — an intersection of the capabilities needed for form rendering, execution, and status tracking.

This means you can pass a partial adapter that only implements what the component actually needs.

<a id="runtimes"></a>
## Runtimes and Profiles

### Ecosystem Runtimes

An `EcosystemRuntime` is a live instance that bundles capabilities for a specific network. Capabilities created within the same runtime share runtime-scoped state (network config, wallet connection, caches) and are disposed together.

Runtimes are created by ecosystem adapter packages:

```tsx
import { ecosystemDefinition } from '@openzeppelin/adapter-evm';

const runtime = await ecosystemDefinition.createRuntime(
'composer', // profile name
ethereumMainnetConfig // network config
);

// Access capabilities from the runtime
const address = runtime.addressing.formatAddress('0x...');
const schema = await runtime.schema.generateFormSchema(contractDef);
const txHash = await runtime.execution.signAndBroadcast(txData, execConfig);

// Clean up when done
runtime.dispose();
```

### Profiles

Adapters support five standard profiles that define which capabilities are included:

| Profile | Use Case | Tier 1 | Tier 2 | Tier 3 |
| --- | --- | --- | --- | --- |
| `declarative` | Address formatting, explorer links | ✓ | — | — |
| `viewer` | Read contract state, no wallet needed | ✓ | ✓ | — |
| `transactor` | Execute transactions, basic wallet | ✓ | ✓ | Execution, Wallet |
| `composer` | Full UI with form rendering | ✓ | ✓ | ✓ (most) |
| `operator` | Administrative tools, access control | ✓ | ✓ | ✓ (all) |

Choose the lightest profile that fits your use case. A dashboard that only displays contract state can use `viewer`; a full transaction builder should use `composer` or `operator`.

For more background on the adapter architecture, see [Building New Adapters](/ui-builder/building-adapters).

### Runtime Lifecycle

```mermaid
sequenceDiagram
participant App as Application
participant RP as RuntimeProvider
participant Adapter as Ecosystem Adapter

App->>RP: Mount with resolveRuntime
App->>RP: setActiveNetworkId("ethereum-mainnet")
RP->>Adapter: createRuntime("composer", networkConfig)
Adapter-->>RP: EcosystemRuntime

Note over RP: Cached by network ID

App->>RP: setActiveNetworkId("polygon-mainnet")
RP->>Adapter: createRuntime("composer", polygonConfig)
Adapter-->>RP: New EcosystemRuntime

Note over RP: Both runtimes cached

App->>RP: Unmount
RP->>RP: dispose() all cached runtimes
```

`RuntimeProvider` maintains a **per-network-id registry** of runtimes. When a network is selected for the first time, the runtime is created asynchronously and cached. On unmount, all runtimes are disposed, releasing any wallet connections, subscriptions, or internal state.

## Execution Strategies

The execution system supports multiple ways to submit a transaction. The adapter selects the appropriate strategy based on the `ExecutionConfig`:

```mermaid
flowchart LR
Form["TransactionForm"] --> Exec["ExecutionCapability"]
Exec --> Strategy{"Method?"}
Strategy -->|EOA| EOA["Direct wallet signing"]
Strategy -->|Relayer| Relay["Gas-sponsored via Relayer"]
EOA --> Chain["Blockchain"]
Relay --> Chain
```

Each ecosystem adapter defines which execution methods it supports. The EVM adapter supports both EOA and Relayer; other ecosystems may support only EOA.

## How It Connects

Putting it all together, here is how a typical application uses UIKit with an Ecosystem Adapter:

```mermaid
%%{init: {'flowchart': {'nodeSpacing': 20, 'rankSpacing': 40}} }%%
flowchart TD
App(["Your React App"])
RP(["RuntimeProvider"])
WSP(["WalletStateProvider"])
TF(["TransactionForm"])
CSW(["ContractStateWidget"])
AdapterEVM(["adapter-evm"])
AdapterStellar(["adapter-stellar"])
Ethereum(["Ethereum"])
Stellar(["Stellar"])

App --> RP --> WSP
WSP --> TF & CSW
RP -.->|createRuntime| AdapterEVM & AdapterStellar
AdapterEVM --> Ethereum
AdapterStellar --> Stellar

style App fill:#e8eaf6,stroke:#5c6bc0,color:#1a237e
style RP fill:#e0f2f1,stroke:#26a69a,color:#004d40
style WSP fill:#e0f2f1,stroke:#26a69a,color:#004d40
style TF fill:#e0f2f1,stroke:#26a69a,color:#004d40
style CSW fill:#e0f2f1,stroke:#26a69a,color:#004d40
style AdapterEVM fill:#fff3e0,stroke:#ff9800,color:#e65100
style AdapterStellar fill:#fff3e0,stroke:#ff9800,color:#e65100
style Ethereum fill:#fce4ec,stroke:#e91e63,color:#880e4f
style Stellar fill:#fce4ec,stroke:#e91e63,color:#880e4f
```

## Next Steps

- [Components](/tools/uikit/components) — Explore all available UI primitives and form fields
- [React Integration](/tools/uikit/react-integration) — Deep dive into providers, hooks, and wallet state
- [Building New Adapters](/ui-builder/building-adapters) — Background on the adapter pattern and ecosystem integrations
Loading
Loading