Skip to content
HomePagesHomePages template kit
Menu

template-kit/size-assets

The template-kit/size-assets authoring rule — what it enforces, why, and how to fix it.

A section’s static assets — the svg, images, and fonts it imports or url()-references — must total ≤ 250 KB raw. Raw, not gzip: images and fonts are already compressed formats, so gzipping them again buys nothing.

A section’s static assets are budgeted by total raw bytes, 250 KB or less. What is measured is every asset the published section actually ships:

  • an svg, image, or font imported directly in Renderer.tsx (or an island), and
  • an svg, image, or font url()-referenced from the section’s own CSS or from a package stylesheet its module graph pulls in — including a webfont @font-faces.

The same asset referenced twice (from both a stylesheet and a component, say) counts once, not twice.

The budget is visible in template-kit check’s configuration and is not author-overridable. A workspace cannot raise it, and there is no per-section exemption.

An svg icon or a product photo a section imports, and a webfont a package’s stylesheet pulls in, both ship to the same page load as the section’s own code and CSS — they are not free just because they never appear in a byte-budget an author is used to watching.

Fonts are the sharpest case. A url()-referenced webfont used to inline as part of the compiled stylesheet, which made a large font look like a CSS problem: trimming your own rules never fixed it, because the bytes were never your CSS to begin with. This rule separates that weight into its own budget — a font, an icon, or an image is measured as what it is, and the stylesheet budget (size-section-css) is left to measure only what it actually contains.

Two moves, in order of how often they work:

  1. Shrink or subset the asset. A full variable font family, shipped for three weights actually used, is the usual cause — subset it to the characters and weights the section renders. An unoptimized PNG is the other common case — recompress it, or switch to a format built for the content (webp/avif for photos, svg for icons).
  2. Drop assets the section does not use. A copied-in icon set or a leftover preview image that never renders still ships its bytes — delete what the section does not reference.
sections/hero/Renderer.tsx
import "brandfont/css"; // ← ships the package's full variable font family
export default function Renderer() {
return <h1 style={{ fontFamily: "BrandFont" }}>Welcome home</h1>;
}
sections/hero/Renderer.tsx
import heroIcon from "./assets/hero-icon.svg"; // ← a small, single-purpose asset
export default function Renderer() {
// Uses a font the template's theme already declares (`--tr-font-<name>`),
// which costs nothing because it is already loaded — no package font import.
return (
<h1 className="tr-font-display">
<img src={heroIcon} alt="" /> Welcome home
</h1>
);
}
  • size-section-css — the stylesheet budget this rule was split out of; a url()-referenced font now counts here, not there.
  • size-renderer-bundle — the same idea applied to the section’s JavaScript.
  • Theme and CSS — the fonts and tokens the page already loads, which cost you nothing to reuse.