- Core UI packages (
@openzeppelin/ui-types,@openzeppelin/ui-utils,@openzeppelin/ui-styles,@openzeppelin/ui-components,@openzeppelin/ui-renderer,@openzeppelin/ui-react,@openzeppelin/ui-storage) are maintained in the separateopenzeppelin-uimonorepo and consumed via npm. - The builder app (
apps/builder) remains in this repository. - Ecosystem adapter packages are maintained in the dedicated
openzeppelin-adaptersmonorepo and consumed by Builder and other products via published packages or approved local-repo overrides during development. - All chain-specific logic, dependencies, and polyfills live exclusively in adapter
packages (
packages/adapter-*in the adapter monorepo). - Adapters MUST publish an EcosystemExport (
ecosystemDefinition) from@openzeppelin/adapter-*packages: metadata,networks,capabilities, andcreateRuntime(profile, networkConfig, options)returning anEcosystemRuntimewhose fields are capability implementations. - The builder MUST resolve runtimes through dynamic ecosystem registration via the
ecosystem manager (
apps/builder/src/core/...), usingcreateRuntime— not ad hoc monolithic adapter classes. - Adapter packages MUST NOT declare chain-specific dependencies in chain-agnostic imports; they own their network concerns.
- Validation rules originate in the relevant runtime capability; the addressing
capability's
isValidAddress(address: string, addressType?: string)supports chain-specific behavior. - The EVM adapter is the reference implementation; all new adapters MUST mirror its structure, naming, and patterns. Stellar mirrors EVM wherever applicable.
- Rationale: Preserves ecosystem neutrality and predictable adapter boundaries to sustain long-term maintainability.
- TypeScript strictness, shared linting, and formatting rules apply across the monorepo.
consoleusage in source code is prohibited; useloggerfrom@openzeppelin/ui-utilsinstead (exceptions only in tests or scripts).- Logging is disabled by default outside development; enable explicitly via
logger.configure({ enabled: true, level }). anytypes are disallowed without explicit justification; prefer precise generics.- Public library APIs MUST include JSDoc annotations as configured.
- Rationale: Enforces consistent quality gates that prevent regressions and ensures actionable diagnostics across packages.
pnpmis the sole package manager; usepnpm -rfor workspace commands.- The Builder application (
apps/builder) builds with the repository-standard Vite stack. This repository does not publish npm packages; the app is private and ships through container deployment (staging and production workflows). - Published
@openzeppelin/ui-*and@openzeppelin/adapter-*dependencies are resolved from the npm registry (or local overrides per the development workflow). - Core UI packages are versioned and released from the
openzeppelin-uirepository using its own release process. - Adapter packages are versioned and released from the
openzeppelin-adaptersrepository (including RC and stable channels as defined there). ui-builderowns Builder CI quality gates, staging and production deployment orchestration, and keeping export metadata (apps/builder/src/export/versions.tsand related checks) aligned with resolved published versions.- CI MUST run automated tests, linting, and type checks on pull requests and
appropriate
mainbranch events; merge criteria follow team policy. - Shared configs (
tailwind.config.cjs,postcss.config.cjs,components.json) are consumed via lightweight proxies. - Rationale: Matches automation to an application-only repository while keeping library publication boundaries clear.
- A single design system governs the builder, renderer, and exported apps.
- Styling leverages Tailwind CSS v4 with shadcn/ui primitives via
@openzeppelin/ui-stylesand root configs. - Use the
cnutility from@openzeppelin/ui-utilsfor class composition. - Prefer
lucide-reacticons; avoid emojis or inline raw SVG when reusable assets exist. - Apply standard Tailwind sizing tokens; use arbitrary values only with documented justification.
- Follow form layout patterns such as
flex flex-col gap-2orspace-y-*for spacing consistency. - Rationale: Guarantees cohesive UI/UX and reduces maintenance overhead across shared surfaces.
- Vitest is the standard for unit and integration tests; use Testing Library for component behavior where appropriate.
- Coverage metrics are tracked in CI; adapter docs and architectural references MUST remain current when interfaces change.
- Exported apps MUST build as standalone React + Vite bundles with runtime
configuration supplied via
AppConfigService(public/app.config.jsonfor exports). - Exported apps use
@openzeppelin/ui-*packages (notui-builder-*); version strategy varies by environment: local usesfile:for tarballs, staging uses RC versions, production uses stable npm versions. - Feature flags gate functionality according to ecosystem readiness.
- Rationale: Ensures reliable distribution channels and prevents regressions in consumer-facing exports.
- All business logic (services, adapters, validators, storage, networking, transforms) MUST follow TDD: write failing tests first, implement minimal code, then refactor.
- UI components in
.tsxfiles are exempt but should use interaction tests (e.g., Testing Library) where feasible. - Vitest remains the standard runner; use mocking only when essential to keep tests fast and focused.
- Rationale: Preserves confidence in critical logic and enforces disciplined implementation sequencing.
- Existing utilities, types, services, and patterns MUST be preferred over new implementations unless reuse compromises integrity.
- Conduct thorough codebase analysis before planning or implementation to
identify reusable modules (e.g., adapters,
AppConfigService, transformers). - Introduce new modules only when reuse is impossible; document rationale and alternatives.
- Extending adapter interfaces in
@openzeppelin/ui-typesrequires coordinating with theopenzeppelin-uirepository maintainers and updating associated lint rules (e.g.,no-extra-adapter-methods). - Shared logic across adapters belongs in
@openzeppelin/ui-utilsor@openzeppelin/ui-types; avoid duplication of chain-agnostic behavior. - Document reuse decisions in specs and plans; reviewers enforce compliance with this principle.
- Rationale: Minimizes redundancy, keeps abstractions aligned, and streamlines onboarding.
- Do not add chain-specific code or polyfills to chain-agnostic imports; adapters own network concerns.
- Data schemas and shared types have a single source of truth in
@openzeppelin/ui-types. - Prefer shared utilities from
@openzeppelin/ui-utils(e.g.,logger,AppConfigService,cn, ID generation); use lodashdebouncewhen debouncing is required. - Avoid noisy logging; rely on structured, level-based logs only when investigating issues.
- Contract comparisons MUST operate on raw contract definitions (ABI/IDL/etc.),
not on internal
ContractSchemarepresentations. - Security: do not hardcode secrets; use runtime configuration.
- Use
pnpmfor all tasks (pnpm dev,pnpm build,pnpm test,pnpm -r format:check,pnpm fix-all). - Local UI development: Run
pnpm dev:localto use the sharedoz-ui-devworkflow backed by the checked-in.openzeppelin-dev.jsonand.pnpmfile.cjsfiles. Runpnpm dev:npmto switch back to published npm packages without rewriting committed dependencies. - Local adapter development: Use the canonical
LOCAL_ADAPTERS_PATHconvention when resolving@openzeppelin/adapter-*packages from a sibling checkout of../openzeppelin-adapters. Compatibility aliases may exist temporarily during migration, but repository docs must converge on the canonical variable. - Docker testing: Run
pnpm docker:devto build and run the Docker container locally. - Commit messages follow Conventional Commits and pass commitlint; Commitizen
(
pnpm commit) is available. - Before opening a PR, ensure tests, type checks, and linting pass
workspace-wide. Changes that affect exported dependency pins MUST run
pnpm update-export-versionsand commit updatedversions.ts(and snapshot tests when applicable) so Check Version Sync and related CI checks pass. - Adapter contributions MUST follow the Adapter Architecture Guide:
capability factories,
createRuntimeprofiles, ecosystem registration, and strictEcosystemExport/ peer version compliance. - Code review enforces constitutional adherence, architecture boundaries, and design system consistency.
- Reuse-First Gate: reviewers verify reuse attempts before approving new modules.
- This constitution supersedes other practices for architecture, quality, and workflow standards; non-negotiable rules MUST be enforced during development and review.
- Amendments require a documented proposal, updates to relevant guides/READMEs, migration notes if applicable, and approval via PR review.
- Repository-boundary changes affecting adapter ownership, release automation, or local-development contracts MUST be ratified here before implementation PRs are merged.
- Breaking changes to export contracts, the export CLI, or other documented
consumer integration surfaces MUST include migration notes in the PR and use
conventional commits (e.g.,
feat!,BREAKING CHANGE:) for visibility. Library packages consumed from other OpenZeppelin repositories follow those repositories’ versioning policies. - CI enforces compliance; PRs violating constitutional rules MUST be corrected before merge.
Version: 1.5.2 | Ratified: 2025-09-17 | Last Amended: 2026-04-02