PHPackages                             dandoetech/bff-metadata - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. dandoetech/bff-metadata

ActiveLibrary

dandoetech/bff-metadata
=======================

Framework-agnostic BFF UI metadata core: derive frontend-ready Resource UI metadata from a central Resource Registry with override support.

v0.2.0(2d ago)101MITPHPPHP ^8.2CI passing

Since Mar 15Pushed 2d agoCompare

[ Source](https://github.com/dandoetech/bff-metadata)[ Packagist](https://packagist.org/packages/dandoetech/bff-metadata)[ Docs](https://github.com/dandoetech/bff-metadata)[ RSS](/packages/dandoetech-bff-metadata/feed)WikiDiscussions main Synced today

READMEChangelogDependencies (4)Versions (3)Used By (1)

DanDoeTech BFF Metadata
=======================

[](#dandoetech-bff-metadata)

> **Pre-release** — Architecture by senior tech lead, implementation largely AI-assisted with human review. Not fully reviewed. Architecture may change before v1.0.0.

Generate frontend-ready UI metadata from a Resource Registry. Derives table columns, form layouts, field widgets, and action buttons — consistently across resources, with per-project overrides. Framework-agnostic.

Installation
------------

[](#installation)

```
composer require dandoetech/bff-metadata
```

Requires [`dandoetech/resource-registry`](https://github.com/dandoetech/resource-registry).

Quick Start
-----------

[](#quick-start)

```
use DanDoeTech\BffMetadata\Builders\DefaultMetadataBuilder;

// $resource is any ResourceDefinitionInterface (from registry or built manually)
$builder = new DefaultMetadataBuilder();
$metadata = $builder->forResource($resource);

echo json_encode($metadata->toArray(), JSON_PRETTY_PRINT);
```

Output:

```
{
  "key": "product",
  "label": "Product",
  "fields": {
    "name": { "name": "name", "widget": "text", "required": true },
    "price": { "name": "price", "widget": "number", "required": true, "props": { "step": 0.01 } },
    "category": { "name": "category", "widget": "relation", "props": { "targetResource": "category", "multiple": false } },
    "category_name": { "name": "category_name", "widget": "text", "readOnly": true }
  },
  "table": {
    "columns": ["name", "price", "category", "category_name"],
    "defaultSort": "-created_at",
    "density": "comfortable"
  },
  "create": { "layout": [["name", "price"], ["category"]] },
  "update": { "layout": [["name", "price"], ["category"]] },
  "actions": [
    { "name": "create", "kind": "primary" },
    { "name": "delete", "kind": "danger", "confirm": true }
  ]
}
```

### Applying Overrides

[](#applying-overrides)

Customize the generated metadata without modifying the resource definition:

```
use DanDoeTech\BffMetadata\Builders\OverrideApplier;

$overrides = [
    'fields' => [
        'price' => ['label' => 'Price (EUR)', 'props' => ['step' => 0.5]],
    ],
    'table' => ['columns' => ['name', 'price'], 'defaultSort' => '-price'],
];

$final = (new OverrideApplier())->apply($metadata, $overrides);
```

> **Laravel users:** Use [`dandoetech/laravel-bff`](https://github.com/dandoetech/laravel-bff) for REST endpoints, policy-based visibility, and caching decorators.

API Overview
------------

[](#api-overview)

### Core

[](#core)

ClassPurpose`DefaultMetadataBuilder`Implements `MetadataProviderInterface` — generates metadata from a resource definition`OverrideApplier`Applies per-project tweaks onto generated metadata`I18nResolver`Optional translation hook for labels and help text### Metadata Value Objects

[](#metadata-value-objects)

ClassContents`ResourceUiMetadata`Top-level container — fields, table, forms, actions, extensions. Has `toArray()``FieldUiMetadata`Widget type, label, help, required, readOnly, props, options, order, width`TableMetadata`Column list, defaultSort, density`FormMetadata`2D layout grid (field names per row), submitOnEnter`ActionUiMetadata`Name, label, kind (`primary`/`default`/`danger`), confirm flag### Contract

[](#contract)

```
interface MetadataProviderInterface
{
    public function forResource(ResourceDefinitionInterface $resource): ResourceUiMetadata;
}
```

Implement this for decorators (policy filtering, caching, logging).

### Widget Mapping

[](#widget-mapping)

FieldTypeWidget`String``text``Integer``number``Float``number` (props: `step: 0.01`)`Boolean``checkbox``DateTime``date``Json``json`Relations`relation` (props: `targetResource`, `multiple`)### Computed Fields

[](#computed-fields)

Computed fields from the registry are included as read-only fields in the table but excluded from form layouts, since they are derived values.

### I18n

[](#i18n)

Pass a translator callable to resolve labels and help text:

```
$i18n = new I18nResolver(fn (string $key) => $translations[$key] ?? null);
$builder = new DefaultMetadataBuilder(i18n: $i18n);
```

Translation keys follow the pattern `resource.{key}.label`, `field.{key}.{name}.label`, `action.{key}.{name}`.

Testing
-------

[](#testing)

```
composer install
composer test        # PHPUnit
composer qa          # cs:check + phpstan + test
```

License
-------

[](#license)

MIT

###  Health Score

38

—

LowBetter than 86% of packages

Maintenance99

Actively maintained with recent releases

Popularity2

Limited adoption so far

Community8

Small or concentrated contributor base

Maturity37

Early-stage or recently created project

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~4 days

Total

2

Last Release

2d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/7db403e7ef98a1eb428f771172dfa0edbd6f7c72d217fad0571992bee2cc089d?d=identicon)[dandoetech](/maintainers/dandoetech)

---

Top Contributors

[![dandoetech](https://avatars.githubusercontent.com/u/5097406?v=4)](https://github.com/dandoetech "dandoetech (33 commits)")

---

Tags

phpuimetadatafrontendSPAbff

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan

Code StylePHP CS Fixer

Type Coverage Yes

### Embed Badge

![Health badge](/badges/dandoetech-bff-metadata/health.svg)

```
[![Health](https://phpackages.com/badges/dandoetech-bff-metadata/health.svg)](https://phpackages.com/packages/dandoetech-bff-metadata)
```

###  Alternatives

[redchamps/module-clean-admin-menu

It will merge all third party extensions menu items to single menu item named 'Extensions'.

163405.1k](/packages/redchamps-module-clean-admin-menu)[kiwilan/php-ebook

PHP package to read metadata and extract covers from eBooks, comics and audiobooks.

3413.7k](/packages/kiwilan-php-ebook)[rockys/ex-admin-thinkphp

Ex-admin-thinkphp 是一个基于Ant Design of Vue + Thinkphp 开发而成后台系统构建工具，无需关注页面模板JavaScript，只用php代码即可快速构建出一个功能完善的后台系统。

173.0k](/packages/rockys-ex-admin-thinkphp)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
