nowo-tech / brand-contracts
Shared brand contract for PHP apps and nowo-tech bundles: brand name, colours and logo assets a host provides, plus colour math for emails and PDFs. Framework-free.
Requires
- php: >=8.2 <8.6
- ext-mbstring: *
- symfony/translation-contracts: ^3.4
Requires (Dev)
- friendsofphp/php-cs-fixer: ^3.0
- igor-php/igor-php: ^0.10.1
- nowo-tech/phpstan-frankenphp: ^1.0
- phpstan/phpstan: ^2.0
- phpunit/phpunit: ^11.5
- rector/rector: ^2.0
Suggests
None
Provides
None
Conflicts
None
Replaces
None
This package is auto-updated.
Last update: 2026-11-08 21:18:57 UTC
README
⭐ Found this useful? Install from Packagist · Give it a star on GitHub so more developers can find it.
Brand Contracts — the shared brand contract for PHP apps and nowo-tech bundles: the brand name, colours and logo
assets a host provides, read the same way by UI shells, PWA manifests, emails, PDFs, legal texts and SEO tags. It is a
tiny, framework-free package (interfaces and value objects, plus colour math for renderers that cannot use CSS
color-mix()). A provider implements one interface; every consumer works without a provider and keeps its own
configuration as the fallback. PHP 8.2+.
This bundle is FrankenPHP worker mode friendly.
Value objects are immutable and the package keeps no static state, so a worker that never resets the kernel is safe. See docs/FRANKENPHP-WORKER-AUDIT.md.
Features
BrandProviderInterface: one method,getBrand(): Brand. InstanceSettings implements it; a host can too, in a few lines. No default provider: consumers keep their config as the fallback.Brand: name (never empty), short name (at most 12 graphemes), eyebrow (string or translatable), wordmark, light and darkBrandColors, resolved assets,isDefaultand aversionhash for ETags and cache keys.- Logo fallback chain:
Brand::asset('favicon')tries favicon, mark, app icon (spec 220, section 4.2). BrandColors: seven#rrggbbcolours per mode, validated and lower-cased;primaryContrast(),mix().ColorMath: WCAG luminance and contrast, sRGB mixes equal to CSScolor-mix(in srgb, …), UiKit's derived shades in hex, the advisory contrast checks.- Safe assets:
BrandAssetaccepts only root-relative orhttps://URLs; uploads are raster only and never inline-safe;BrandAssetDataUribuilds data URIs from sniffed bytes for emails and PDFs.
Installation
composer require nowo-tech/brand-contracts
See docs/INSTALLATION.md.
Quick start
use Nowo\Brand\Contract\BrandProviderInterface; final class InvoiceMailer { public function __construct(private readonly ?BrandProviderInterface $brand = null) {} public function senderName(): string { return $this->brand?->getBrand()->name ?? 'My App'; // own config stays the fallback } }
Requirements
- PHP 8.2+ (
>=8.2 <8.6) withmbstring symfony/translation-contracts^3.4 (the only runtime dependency; no framework needed)
Configuration
None: the package has no configuration. See docs/CONFIGURATION.md.
Usage
See docs/USAGE.md. What may change in a 1.x minor (new optional colour keys, new BrandAssetOrigin
cases, new shades() keys) is listed under API stability.
Development
make up
make install
make test
make cs-check
make phpstan
make igor
make test-coverage-100
make release-check
Documentation
- Installation
- Configuration
- Usage
- Contributing
- Code of Conduct
- Changelog
- Upgrading
- Release
- Security
- Engram
- Spec-driven development
- GitHub Spec Kit
Additional documentation
- PSR evaluation (REQ-CS-007)
- FrankenPHP worker audit (kernel not reset)
- GitHub Actions CI requirements
Tests and coverage
- Tests: PHPUnit (PHP), unit tests only (no I/O, no framework): validation tables, fallback chains, colour math checked against UiKit's emitter values for the Beacon palette
- PHP: 100% (gate enforced in CI by
composer test-coverage-100, no exclusions) - TS/JS: N/A
- Python: N/A
License and author
MIT · Nowo.tech · Héctor Franco Aceituno
