Integrating Frontend Output
This guide shows the backend side of the handover after a frontend package is released: which generated files matter, where to place them, and how to reference hashed CSS, JavaScript, and icons without fighting the cache.
Overview
When the Frontend team ships a new package, the Backend team usually receives a small bundle of generated files. Some of them are only useful for comparison, while others are required at runtime. Knowing which is which saves a fair amount of avoidable confusion.
The handover normally includes the following items:
-
/PreciseAlloy.Patterns - folder
This folder contains HTML snapshots of rendered frontend pages at the time the package was created. It helps the Backend team compare markup changes and spot what needs reintegration.
You do not need to deploy these files to run the website. -
/PreciseAlloy.Web/wwwroot/assets - folder
This folder contains the compiled frontend assets, including CSS, JavaScript, icons, fonts, and images required by the site. -
/PreciseAlloy.Web/wwwroot/assets/hashes.json - file
This file maps each generated asset to its content hash. It must be deployed with the site so the backend can generate cache-busted asset URLs correctly. If it is missing, the cache buster stops being useful and the CDN will happily serve stale files with great confidence.
The Frontend team usually prepares these files as part of the release pipeline, so the Backend team does not need to build them manually. If you do need to generate them yourself, see Frontend integration.
The following files and folders are generated by the frontend integration pipeline. Do not edit them by hand unless you enjoy losing your work a few minutes later.
- /PreciseAlloy.Patterns/
- /PreciseAlloy.Web/wwwroot/assets/css/
- /PreciseAlloy.Web/wwwroot/assets/fonts/
- /PreciseAlloy.Web/wwwroot/assets/images/
- /PreciseAlloy.Web/wwwroot/assets/js/
- /PreciseAlloy.Web/wwwroot/assets/vendors/
- /PreciseAlloy.Web/wwwroot/assets/hashes.json
Any manual changes in those locations will be overwritten by the next frontend build.
Integration
Copy the markup file
Start by copying the markup provided by the Frontend team into the matching backend view file.
For example, if you need to integrate the Hero block and the Frontend team points you to the static site's Home page, open the matching Patterns Home page. Find the Hero block markup there, like the simplified example below:
<section class="zzz-o-hero">
<h1>WELCOME</h1>
<img src="/samples/image-1.svg" alt="hero">
<a href="https://www.office.com/">
<span>Explore</span>
<svg viewBox="0 0 19 19" width="19" height="19">
<use xlink:href="/icons.svg#zzz-view"></use>
</svg>
</a>
<!-- <link rel="stylesheet" href="/assets/css/b-hero.css"> -->
<!-- <script type="module" src="/assets/js/b-hero.js"></script> -->
</section>Copy that markup into the backend .cshtml view for the Hero block, then replace the hard-coded values with model data.
Handling hashes.json
Assume you have a hashes.json file at /PreciseAlloy.Web/wwwroot/assets/hashes.json with content like this:
{
"/assets/css/style-base.css": "Y3_rQ26JDf",
"/assets/css/b-hero.css": "t8cxlFd_dF",
"/assets/js/react-loader.0x4d7d0ab2.js": "",
"/assets/js/main.js": "iX_2YqQ2z7",
"/assets/js/hero.js": "A_CKPf-kTa",
"/icons.svg": "SeT74kfn_L"
}To make this manageable, the backend exposes HTML extension methods that generate the correct CSS and JavaScript tags and append the matching hash automatically. For the full list of available helpers, see /PreciseAlloy.Utils/Extensions/HtmlExtensions.cs.
Including CSS files
If you want to include b-hero.css into the <head> element of your page, use the following helper:
@{
Html.RequireStyle("/assets/css/b-hero.css").AtHeader();
}The output will be:
<link href="/assets/css/b-hero.css?v=t8cxlFd_dF" rel="stylesheet">The ?v=t8cxlFd_dF part represents the hash of the file's content, generated at the frontend's compile time. This approach ensures proper caching. If the file remains unchanged, the hash value remains the same, allowing browsers and/or CDN to cache it for extended periods. When the file content changes, the hash value changes as well, prompting browsers to retrieve the updated file to avoid any caching issues.
You can call the above method multiple times, but the rendered HTML will contain exactly one instance of the link to that CSS file.
Including JavaScript files
To include hero.js at the footer of your page, use the following method:
@{
// !!! Caution: see the note below
Html.RequireScript("/assets/js/hero.js").AtFooter();
}The output will be:
<script src="/assets/js/hero.js?v=A_CKPf-kTa" type="module"></script>Like the CSS helper, the JavaScript helper appends the hash to the asset URL so cache busting stays consistent.
The footer example above only demonstrates the API. Unless a component explicitly requires something else, include both CSS and JavaScript assets in the header. Styles are available immediately, and ES modules are still deferred by default, so they will not block the page the way old script tags used to.
Obtaining the path directly
If you only need the asset URL and not a full HTML tag, call @Html.GetCacheBusterPath() directly. For example:
<img src="@Html.GetCacheBusterPath("/icons.svg")">The output will be:
<img src="/icons.svg?v=SeT74kfn_L">Sample integration
Here is a simple example of the Hero markup integrated into a backend view.
Null checks and surrounding view logic are omitted for brevity.
@model HeroViewModel;
@{
// Styles
Html.RequireStyle("/assets/css/b-hero.css").AtHeader();
// Scripts
Html.RequireScript("/assets/js/hero.js").AtHeader();
// Icons
var iconPath = Html.GetCacheBusterPath("/icons.svg");
}
<section class="zzz-o-hero">
<h1>@Model.Heading</h1>
<img src="@Model.ImageSrc" alt="@Model.AlternativeText">
<a href="@Model.CtaUrl">
<span>@Model.CtaText</span>
<svg viewBox="0 0 19 19" width="19" height="19">
<use xlink:href="@iconPath#zzz-view"></use>
</svg>
</a>
</section>Special Case for React Components
There is one special case: react-loader.0x....js acts as the entry point for React components that use client-side rendering. You only need to include it once in the layout. In the <head>, use:
<script type="module" src="@Html.GetWidgetAssetPath("react-loader")"></script>This helper searches for a file whose name contains /react-loader.0x and returns the matched path.
The output will be:
<script type="module" src="/assets/js/react-loader.0x4d7d0ab2.js"></script>Conclusion
Once the generated files are in place, backend integration is mostly about discipline: copy the right markup, reference assets through the helper methods, and leave generated output alone. That keeps cache busting reliable and makes the next frontend release much less dramatic.