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(1mo ago)0210MITPHPCI failing

Since Feb 28Pushed 3w 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 3w 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

40

—

FairBetter than 86% of packages

Maintenance95

Actively maintained with recent releases

Popularity11

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

31d 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

101466.4k45](/packages/friendsoftypo3-content-blocks)[wazum/sluggi

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

41515.2k](/packages/wazum-sluggi)[wapplersystems/ws-scss

Compiles SCSS to CSS at runtime with caching, TypoScript variables and EXT: import support

11144.8k7](/packages/wapplersystems-ws-scss)[praetorius/vite-asset-collector

Use AssetCollector to embed frontend assets generated by vite

54299.7k1](/packages/praetorius-vite-asset-collector)[b13/assetcollector

Asset collector - Add CSS and SVG files and strings as inline style tag/inline svg to the html code.

10123.2k](/packages/b13-assetcollector)[eliashaeussler/typo3-solver

Solver - Extends TYPO3's exception handling with AI generated solutions. Problems can also be solved from command line. Several OpenAI parameters are configurable and prompts and solution providers can be customized as desired.

302.1k](/packages/eliashaeussler-typo3-solver)

PHPackages © 2026

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