PHPackages                             maispace/assets - 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. [Utility &amp; Helpers](/categories/utility)
4. /
5. maispace/assets

ActiveTypo3-cms-extension[Utility &amp; Helpers](/categories/utility)

maispace/assets
===============

Intelligent asset pipeline for TYPO3 with critical CSS, SVG sprites, responsive images, font preloading, and self-optimising above-fold detection.

v14.0.0(2mo ago)0214MITPHPCI failing

Since Feb 28Pushed 2mo agoCompare

[ Source](https://github.com/mai-space-de/typo3-extension-assets)[ Packagist](https://packagist.org/packages/maispace/assets)[ RSS](/packages/maispace-assets/feed)WikiDiscussions main Synced 4w ago

READMEChangelog (2)Dependencies (14)Versions (10)Used By (0)

maispace/mai-assets — TYPO3 Extension
=====================================

[](#maispacemai-assets--typo3-extension)

[![PHP](https://camo.githubusercontent.com/187240af044d09d5b14a1d9d9ebdf3f7a993e4c7bc09bdb46b4ba661a891bf5b/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f5048502d382e322532422d626c7565)](https://www.php.net/)[![TYPO3](https://camo.githubusercontent.com/8e07c24b7f613f6d30d4836b4d39c2b1722b1f030602202a878615f2d6cf25fa/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f5459504f332d31332e342532304c54532d6f72616e6765)](https://typo3.org/)[![License: GPL v2](https://camo.githubusercontent.com/77e900ae34f8da9ccccc42662fce61a94ab07ddbfe3f7d066178e824f3673dbd/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4c6963656e73652d47504c25323076322d626c75652e737667)](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html)

The canonical asset pipeline for the entire extension set. Provides Fluid ViewHelper-based asset inclusion with minification, SCSS compilation, and SVG sprite building. Also manages the TYPO3 file abstraction layer via `cms-filelist` and `cms-filemetadata`. All other extensions that need SCSS compilation or asset minification depend on this extension rather than pulling in `scssphp` or minification libraries directly.

**Requires:** TYPO3 13.4 LTS / 14.1 · PHP 8.2+

---

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

[](#installation)

```
composer require maispace/mai-assets
```

---

ViewHelpers
-----------

[](#viewhelpers)

The extension registers the `mai` namespace globally via TypoScript:

```
config.namespaces.mai = Maispace\MaiAssets\ViewHelpers

```

Once the extension is loaded, all ViewHelpers below are available in Fluid templates with the `mai:` prefix. If you need to declare the namespace manually (e.g. in a standalone template), add:

```
{namespace mai=Maispace\MaiAssets\ViewHelpers}
```

---

### CSS &amp; JS ViewHelpers

[](#css--js-viewhelpers)

#### `` — Stylesheet inclusion

[](#maicss--stylesheet-inclusion)

Compiles SCSS on demand, minifies CSS, auto-computes SRI hashes, handles critical inlining, and registers HTTP/103 Early Hints preload candidates. Returns an empty string for non-critical files (the asset is registered with the TYPO3 `AssetCollector`); returns a `` block for critical files.

ArgumentTypeRequiredDefaultDescription`identifier`stringyes—Deduplication key; duplicate identifiers are silently ignored`src`stringyes—`EXT:` path or absolute path to a `.css` or `.scss` file`priority`bool`false`Render in `` before page CSS when `true`; footer otherwise`minify`bool*global*Per-call override; inherits `plugin.tx_maiassets.settings.enableMinification` when omitted`critical`string`'auto'``'auto'` detect from observer data · `'true'` always inline · `'false'` always link`media`string`'all'`CSS `media` attribute on the `` tag`nonce`string`''`CSP nonce injected on the inline `` when the file is critical`integrity`string`''`SRI hash; auto-computed from the compiled file when empty and the file is local`crossorigin`string`''``crossorigin` attribute on the `` tag**Critical mode:** when `critical="true"` or the page observer marks the current page as above-fold critical, the CSS is compiled and inlined as `…`. An Early Hints preload candidate is registered in both modes.

```

```

---

#### `` — Script inclusion

[](#maijs--script-inclusion)

Minifies JavaScript, auto-computes SRI hashes, handles critical `fetchpriority`, ES6 modules, and registers HTTP/103 Early Hints preload or modulepreload candidates. Returns an empty string (the script is registered with the TYPO3 `AssetCollector`).

ArgumentTypeRequiredDefaultDescription`identifier`stringyes—Deduplication key`src`stringyes—`EXT:` path or absolute path to a `.js` file`priority`bool`false``true` = inject in `` · `false` = footer`minify`bool*global*Per-call override; inherits global minification setting when omitted`critical`string`'auto'``'auto'` detect · `'true'` add `fetchpriority="high"` · `'false'` normal`defer`bool`true`Add `defer` attribute; ignored for `type="module"` and critical scripts`async`bool`false`Add `async` attribute; mutually exclusive with `defer``type`string`''`MIME type; set `'module'` for ES6 modules (browser defers automatically)`nomodule`bool`false`Add `nomodule` for legacy-browser fallback bundles`nonce`string`''`CSP nonce`integrity`string`''`SRI hash; auto-computed for local files when empty`crossorigin`string`''``crossorigin` attribute**Module scripts:** setting `type="module"` enables ES6 module semantics. Early Hints use `modulepreload`instead of `preload` for these scripts. **Critical scripts:** `defer` is suppressed and `fetchpriority="high"` is added. An Early Hints preload candidate is registered.

```

```

---

### Image ViewHelpers

[](#image-viewhelpers)

#### `` — Single-tag responsive image

[](#maiimageresponsive--single-tag-responsive-image)

Generates a complete `` element with AVIF, WebP, and JPEG `srcset` variants per named breakpoint. Use when the same crop is appropriate for all viewport sizes.

ArgumentTypeRequiredDefaultDescription`image`objectyes—FAL `FileReference` or `File` object`breakpoints`arrayyes—Associative array of breakpoint label → pixel width, e.g. `{mobile: 400, desktop: 1200}``sizes`stringyes—`sizes` attribute, e.g. `'(max-width: 767px) 100vw, 50vw'``critical`string`'auto'``'auto'` · `'true'` · `'false'``elementUid`int`0`Content element UID for auto-criticality detection`alt`string`''`Alt text on the fallback ```class`string`''`CSS class on the `` elementWhen the image is critical, `loading="eager"`, `fetchpriority="high"`, and `decoding="sync"` are set, and an Early Hints preload candidate for the AVIF source is registered.

```

```

Rendered output (simplified):

```

```

---

#### `` + `` — Art-directed responsive image

[](#maiimagepicture--maiimagepicturesource--art-directed-responsive-image)

Use these two ViewHelpers together when different crops, aspect ratios, or format selections are needed per breakpoint. `` provides the outer `` wrapper and resolves criticality; `` children define each `` element.

**`` arguments:**

ArgumentTypeRequiredDefaultDescription`image`objectyes—FAL `FileReference` or `File` object`alt`string`''`Alt text on the fallback ```width`int`0`Fallback image pixel width (0 = original width)`height`int`0`Fallback image pixel height`critical`string`'auto'``'auto'` · `'true'` · `'false'``elementUid`int`0`Content element UID for auto-criticality detection`quality`int`85`Fallback image quality (1–100)`fileExtension`string`''`Fallback image format, e.g. `'jpg'``crossorigin`string`''``crossorigin` attribute on ```class`string`''`CSS class on ``**`` arguments:**

ArgumentTypeRequiredDefaultDescription`media`stringyes—CSS media query for this source, e.g. `'(max-width: 767px)'``srcset`array`[]`Array of widths to generate, e.g. `{0: 400, 1: 800}``sizes`string`''``sizes` attribute`formats`array`['avif', 'webp']`Image formats; order determines `` order in the output`quality`int`85`Image quality (1–100)`width`int`0`Fallback width`height`int`0`Fallback height`` must be a **direct child** of `` and only renders inside that context. When the parent image is critical, the first AVIF source registers an Early Hints preload candidate.

```

```

---

#### `` — Semantic figure wrapper

[](#maiimagefigure--semantic-figure-wrapper)

Wraps child content in a `` element with an optional ``.

ArgumentTypeRequiredDefaultDescription`caption`string`''`Caption text rendered as ``; omitted when empty`class`string`''`CSS class on ```id`string`''``id` attribute on ```role`string`''``role` attribute on `````

```

---

### SVG ViewHelpers

[](#svg-viewhelpers)

#### `` — SVG sprite icon

[](#maisvgicon--svg-sprite-icon)

Renders an inline `` reference that points to the single shared sprite injected after ``. The SVG source file is parsed and registered in the sprite on the first render of each page. Subsequent references to the same identifier use the already-registered symbol.

ArgumentTypeRequiredDefaultDescription`identifier`stringyes—Unique sprite symbol ID; used as the `href="#…"` target`source`stringyes—`EXT:` path to the source `.svg` file`label`string`''`Accessible label; when non-empty renders a meaningful icon with `role="img"` and ```class`string`''`CSS class on the `` element`size`string`'1em'`Inline `width` / `height` CSS value applied as a `style` attributeIcons without a `label` are treated as decorative: `aria-hidden="true"` and `focusable="false"` are added automatically.

```

```

---

#### `` — Inline SVG

[](#maisvginline--inline-svg)

Inlines the full SVG source directly into the HTML. Output is cached by file hash combined with all argument values, so repeated calls with identical arguments return the cached result. `width` and `height` attributes are stripped from the `` root by default so the element scales via CSS.

ArgumentTypeRequiredDefaultDescription`src`stringyes—`EXT:` path or absolute path to the `.svg` file`title`string`''`Injects a `` as the first child element for screen-reader accessibility`ariaLabel`string`''``aria-label` attribute on the `` root; also sets `role="img"``class`string`''`CSS class attribute on the `` root`stripDimensions`bool`true`Strip `width` / `height` from the `` root (recommended; size via CSS)```

```

---

### Video ViewHelper

[](#video-viewhelper)

#### `` — Unified video element

[](#maivideovideo--unified-video-element)

Supports self-hosted files, YouTube and Vimeo privacy-friendly lazy-load facades, and a muted autoplay background mode. All embed types are lazy-loaded by default (`data-lazy` + `preload="none"` or facade pattern). Pass exactly one of `file`, `youtubeId`, or `vimeoId`; for `type="background"` only `file`is supported.

ArgumentTypeRequiredDefaultDescription`file`object`null`FAL `FileReference` for self-hosted video`youtubeId`string`''`YouTube video ID; embeds via `youtube-nocookie.com``vimeoId`string`''`Vimeo video ID; embeds via `player.vimeo.com``poster`object`null`FAL `FileReference` used as poster/thumbnail image`isCritical`bool`false`Above-fold flag for background mode: `true` = eager autoplay, `false` = `data-lazy``type`string`'content'``'content'` — interactive player · `'background'` — muted autoplay loop`title`string`''`Video title for accessibility (`` and ``)`class`string`''`CSS class on the outermost element**Self-hosted source order:** AV1 (`.av1.mp4`) → HEVC (`.hevc.mp4`) → H.264 (original). Variant files are discovered by convention: place `filename.av1.mp4` and `filename.hevc.mp4` alongside the original `filename.mp4`. Missing variants are silently omitted.

**YouTube / Vimeo facades:** a poster image and play button are rendered initially. A JavaScript click handler must clone the `` from the adjacent `` element and replace the facade. No JS library is bundled — implement the activation script in `mai_theme`.

**Background videos** use `autoplay muted loop playsinline`. Above-fold videos (`isCritical="true"`) get `preload="metadata"` and start immediately; below-fold videos get `preload="none" data-lazy` for deferred loading.

```

```

---

Criticality Resolution
----------------------

[](#criticality-resolution)

The `AssetCriticalityResolver` service provides ViewHelpers with a single injection point to query above-fold criticality. Two page-level methods are available:

### `pageHasObserverData(int $pageUid): bool`

[](#pagehasobserverdataint-pageuid-bool)

Returns `true` when **any** viewport bucket (e.g. only desktop) has reported critical UIDs for the page. This is the permissive check — used by `` and `` in `critical="auto"` mode to start inlining as soon as the first visitor's browser reports above-fold elements.

### `pageHasCompleteObserverData(int $pageUid): bool`

[](#pagehascompleteobserverdataint-pageuid-bool)

Returns `true` only when **all** configured viewport buckets (mobile, tablet, desktop) have been reported AND at least one bucket contains non-empty critical UIDs. This is the conservative check — wait until observer data has been accumulated across every viewport size before trusting the auto-criticality decision.

MethodConditionUse case`pageHasObserverData`Any bucket has UIDsQuick warm-up: inline as soon as first observer reports`pageHasCompleteObserverData`All configured buckets have UIDsConservative: wait for full cross-viewport coverageBoth methods delegate to `AboveFoldCacheService` and never touch the database directly.

### `isElementAboveFold(int $elementUid, int $pageUid): bool`

[](#iselementabovefoldint-elementuid-int-pageuid-bool)

Element-level check used by image ViewHelpers. Delegates to `CriticalDetectionService::isCritical()`which resolves through three layers: DB `force_critical` flag → observer cache data → position/sorting heuristic.

---

Development
-----------

[](#development)

### Linting

[](#linting)

```
composer lint:check     # Run all linters
composer lint:fix       # Fix auto-fixable issues
```

### Testing

[](#testing)

```
composer test           # Run all tests
composer test:unit      # Run unit tests only
```

---

License
-------

[](#license)

GPL-2.0-or-later — see [LICENSE](../../LICENSE) for details.

###  Health Score

38

—

LowBetter than 83% of packages

Maintenance86

Actively maintained with recent releases

Popularity12

Limited adoption so far

Community9

Small or concentrated contributor base

Maturity40

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 79.8% 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 ~42 days

Total

3

Last Release

76d ago

Major Versions

v13.1.0 → v14.0.02026-05-23

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/28559477?v=4)[maispace](/maintainers/maispace)[@MaiSpace](https://github.com/MaiSpace)

---

Top Contributors

[![mai-space](https://avatars.githubusercontent.com/u/38419872?v=4)](https://github.com/mai-space "mai-space (83 commits)")[![claude](https://avatars.githubusercontent.com/u/81847?v=4)](https://github.com/claude "claude (17 commits)")[![Copilot](https://avatars.githubusercontent.com/in/1143301?v=4)](https://github.com/Copilot "Copilot (4 commits)")

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan

Code StylePHP CS Fixer

Type Coverage Yes

### Embed Badge

![Health badge](/badges/maispace-assets/health.svg)

```
[![Health](https://phpackages.com/badges/maispace-assets/health.svg)](https://phpackages.com/packages/maispace-assets)
```

###  Alternatives

[friendsoftypo3/content-blocks

TYPO3 CMS Content Blocks - Content Types API | Define reusable components via YAML

103574.3k64](/packages/friendsoftypo3-content-blocks)[contao/core-bundle

Contao Open Source CMS

1301.7M3.0k](/packages/contao-core-bundle)[wazum/sluggi

TYPO3 extension for URL slug management with inline editing, auto-sync, locking, access control, and redirects

40543.5k](/packages/wazum-sluggi)[typo3/cms-redirects

TYPO3 CMS Redirects - Create manual redirects, list existing redirects and automatically createredirects on slug changes.

167.6M84](/packages/typo3-cms-redirects)[typo3/cms-form

TYPO3 CMS Form - Flexible TYPO3 frontend form framework that comes with a backend editor interface.

147.8M284](/packages/typo3-cms-form)[typo3/cms-sys-note

TYPO3 CMS System Notes - Records with messages which can be placed on any page and contain instructions or other information related to a page or section.

116.5M41](/packages/typo3-cms-sys-note)

PHPackages © 2026

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