VOOZH about

URL: https://deepwiki.com/calevans/staticforge/6.4-asset-management

⇱ Asset Management | calevans/staticforge | DeepWiki


Loading...
Last indexed: 11 February 2026 (5f6a2a)
Menu

Asset Management

Purpose and Scope

This document describes StaticForge's asset management system, which handles the registration, aggregation, and injection of CSS and JavaScript files into generated HTML pages. The system provides both manual template control and automatic fallback injection, ensuring assets are included even when templates don't explicitly reference them.

For configuration of cache busting (the cache_buster template variable), see the CacheBuster feature documentation in Built-in Features Reference. For template variable usage more broadly, see Template Variables.


Architecture Overview

StaticForge's asset management operates through three components: the AssetManager service (which maintains asset collections), the TemplateRenderer (which performs injection), and template variables (which allow manual control).

Asset Flow Diagram


Sources: src/Features/MarkdownRenderer/Feature.php44-54 src/Services/TemplateRenderer.php20-24 src/Services/TemplateRenderer.php87-96


AssetManager Service

The AssetManager class is the central registry for CSS and JavaScript assets. It is registered in the dependency injection container and made available to features.

Service Registration

Features retrieve the AssetManager from the container during their register() method:


The AssetManager is then passed to the TemplateRenderer constructor, making it available throughout the rendering pipeline.

Sources: src/Features/MarkdownRenderer/Feature.php44-48 src/Features/HtmlRenderer/Feature.php40-44

Asset Types and Storage

The AssetManager maintains three separate collections:

Asset TypeMethodInjection PointPurpose
StylesgetStyles()Before </head>CSS stylesheets via <link> tags
Head ScriptsgetScripts(false)Before </head>JavaScript that must load before page render
Body ScriptsgetScripts(true)Before </body>JavaScript that can load after DOM construction

Template Variables for Assets

The TemplateVariableBuilder converts AssetManager collections into template variables that can be rendered in Twig templates.

Variable Assignment Flow


Sources: src/Services/TemplateRenderer.php87

Template Variable Usage

Templates access these variables using Twig syntax with the raw filter to prevent HTML escaping:


The raw filter is critical because asset variables contain HTML <link> and <script> tags that must not be escaped.

Sources: templates/staticforce/base.html.twig62-63


Manual Template Asset Inclusion

StaticForge's default templates demonstrate two patterns for including assets: hardcoded includes and block overrides.

Hardcoded Asset Pattern

The base.html.twig template includes core assets directly:



This pattern is used for assets that should be present on every page using the base template.

Sources: templates/staticforce/base.html.twig62 templates/staticforce/base.html.twig107-109

Block Override Pattern

Child templates can include additional assets via the extra_head block:


This allows template-specific asset injection without modifying the base template.

Sources: templates/staticforce/docs.html.twig25-28 templates/staticforce/index.html.twig22-24

Asset URL Construction

All asset URLs follow this pattern:

{{ site_base_url }}assets/[type]/[filename]?{{ cache_buster }}

Where:

  • site_base_url: Configured base URL with trailing slash (from SITE_BASE_URL)
  • type: css, js, or other asset directory
  • filename: Asset filename
  • cache_buster: Optional query parameter for cache invalidation (see CacheBuster feature)

Automatic Asset Injection

When templates don't include asset variables, TemplateRenderer automatically injects them as a fallback mechanism. This ensures assets are never omitted due to template oversights.

Injection Algorithm


Sources: src/Services/TemplateRenderer.php92-96 src/Services/TemplateRenderer.php218-268

Injection Detection Logic

The injection mechanism uses string presence checking to determine if assets were manually included:

CheckLogicAction if False
Styles Presentstrpos($html, $styles) === falseInject before </head>
Head Scripts Presentstrpos($html, $headScripts) === falseInject before </head>
Body Scripts Presentstrpos($html, $scripts) === falseInject before </body>

This approach compares the exact HTML string returned by AssetManager methods against the rendered output. If the string is not found, the system assumes the template didn't include it.

Sources: src/Services/TemplateRenderer.php253-258 src/Services/TemplateRenderer.php262-264

Injection Implementation


Sources: src/Services/TemplateRenderer.php253-264


Integration with Renderer Features

Both the MarkdownRenderer and HtmlRenderer features integrate with the asset system by providing AssetManager to the TemplateRenderer.

Renderer Feature Asset Flow


Sources: src/Features/MarkdownRenderer/Feature.php44-62 src/Features/HtmlRenderer/Feature.php40-53

Optional AssetManager Pattern

The renderer features use a defensive pattern to handle cases where AssetManager is not registered:


This allows the system to function even if asset management is disabled, though with reduced functionality.

Sources: src/Features/MarkdownRenderer/Feature.php44-54 src/Features/HtmlRenderer/Feature.php40-51


Cache Busting Integration

While cache busting is implemented by a separate feature (CacheBuster), it integrates closely with asset management through the cache_buster template variable.

Cache Buster Usage in Templates

Assets that should be cache-busted append the cache_buster variable as a query parameter:


This causes browsers to treat each build as a distinct resource, preventing stale cached assets from being served.

Sources: templates/staticforce/base.html.twig62

Cache Busting Scope

Asset TypeCache BustedReason
Hardcoded Template AssetsYesTemplate explicitly adds ?{{ cache_buster }}
AssetManager-Registered AssetsDepends on FeatureFeature must include cache_buster when registering URL
External CDN AssetsNoExternal URLs should use their own versioning

Feature Asset Registration Patterns

Features that need to include custom assets should follow these patterns.

Feature Asset Registration Flow


Sources: src/Services/TemplateRenderer.php20-24 src/Services/TemplateRenderer.php92-96

Example: Feature Registering Assets

While the exact AssetManager API isn't shown in the provided files, features would typically register assets during their register() method or event handlers:



Asset Injection Points Summary

The following table summarizes where different asset types are injected:

Asset TypeTemplate VariableAuto-Injection PointTypical Usage
CSS Stylesheets{{ styles|raw }}Before </head>All CSS files
Head JavaScript{{ head_scripts|raw }}Before </head>Scripts that must load before DOM
Body JavaScript{{ scripts|raw }}Before </body>Scripts that can defer until after DOM

Injection Priority

When assets are injected automatically, they follow this order:

  1. Styles injected first (before </head>)
  2. Head Scripts injected second (before </head>, after styles)
  3. Body Scripts injected last (before </body>)

This ensures proper cascading and script execution order.

Sources: src/Services/TemplateRenderer.php253-264


Best Practices

For Template Authors

  1. Use the extra_head block for template-specific assets rather than duplicating the entire head section
  2. Include cache_buster query parameter on all local asset URLs: ?{{ cache_buster }}
  3. Use {{ variable|raw }} when outputting asset variables to prevent HTML escaping
  4. Rely on auto-injection as a safety net, but explicitly include asset variables for clarity

For Feature Developers

  1. Check for AssetManager availability before attempting to use it: $container->has(AssetManager::class)
  2. Include cache buster in registered URLs to ensure proper cache invalidation
  3. Use inHead parameter appropriately when registering scripts:
    • false for initialization scripts that must run before DOM ready
    • true for scripts that enhance already-rendered content
  4. Pass AssetManager to TemplateRenderer to enable auto-injection fallback

Sources: src/Features/MarkdownRenderer/Feature.php44-54 templates/staticforce/base.html.twig62 templates/staticforce/docs.html.twig25-28

Refresh this wiki

On this page