How to adopting hinting strip as a design system policy
- Step 1Audit your current font inventory — List every font and weight in the system and check which carry hinting tables. Inspect with [font-metadata-extractor](/font-tools/font-metadata-extractor) or [font-format-identifier](/font-tools/font-format-identifier) to see the table inventory. Inherited legacy assets are usually the heavily-hinted ones with the biggest savings.
- Step 2Pull the audience evidence — Get your OS/browser breakdown. The decisive number is the Windows 7/8 GDI share — the only cohort that reads the hints. Record it; it's the justification your policy will cite.
- Step 3Pilot on one weight — Strip a single body weight, re-compress to WOFF2, and run a visual regression pass against representative pages. Modern audiences see no difference; this de-risks the rollout and gives you a real `Saved %` figure to quote.
- Step 4Define the policy and its one exception — Standardise on stripped + WOFF2 for the default audience. Write the exception explicitly: if legacy-GDI traffic ever exceeds your threshold, serve that cohort the hinted master. Keep the hinted source in version control so the exception is always buildable.
- Step 5Enforce it in the build — Make 'strip → subset → WOFF2' a non-optional pipeline stage (see the CI guide). Because the strip is single-file in the UI, automation owns the per-weight loop. The policy is only real once it's enforced by the build, not a wiki page.
- Step 6Review on a cadence — Re-check the legacy-Windows share each quarter or at each brand refresh. The number only trends down, so the policy gets safer over time — but a dated review keeps it defensible.
Strip-or-keep policy by audience profile
The decision is driven by renderer mix, not by the font. Thresholds are starting points — tune to your product's risk tolerance.
| Audience profile | Legacy-GDI share | Policy |
|---|---|---|
| Consumer web / SaaS, modern traffic | < 1% | Strip all weights + WOFF2 |
| Mixed B2B with some legacy desktop | 1–5% | Strip default; consider split delivery |
| Enterprise intranet pinned to Windows 7/8 | > 5% | Keep hinting for that cohort |
| Apple-only product (Mac + iOS) | 0% | Strip — always safe (CoreText ignores hints) |
| Mobile-first app | ~0% | Strip — autohint engines ignore embedded hints |
What the policy actually mandates per font
The operational contract. Each step maps to a JAD tool; the strip itself has no options to standardise beyond 'always run it'.
| Step | Mandated action | Tool |
|---|---|---|
| 1 | Strip the seven hint tables | hinting-stripper |
| 2 | Re-compress (strip outputs raw TTF) | ttf-to-woff2 |
| 3 | Subset to the system's glyph set | font-subsetter |
| (opt) | Scrub vendor/metadata strings | name-table-cleaner |
| always | Keep hinted master in version control | your repo |
Bandwidth math across a system
Illustrative: a 12-weight system at the mid-point of the 5–20% strip band, before WOFF2. Real figures depend on how heavily your faces were hinted.
| Scope | Per weight | 12 weights |
|---|---|---|
| Heavily-hinted legacy faces (~18%) | −54 KB on 300 KB | ~−648 KB |
| Typical modern web faces (~8%) | −24 KB on 300 KB | ~−288 KB |
| Lightly-hinted faces (~5%) | −15 KB on 300 KB | ~−180 KB |
Cookbook
Policy decisions for real org shapes. Each is an audience call made before the tool runs — the tool itself just removes the same seven tables every time.
Policy clause for a consumer product
ExampleThe kind of language to pin in your design system docs so the debate stops recurring.
FONT POLICY (v1, 2026-06): All web fonts ship UNHINTED + WOFF2. Rationale: Win7/8 GDI traffic = 0.3% (below 1% threshold). Pipeline: hinting-stripper -> font-subsetter -> ttf-to-woff2. Hinted masters retained in /design-tokens/fonts/src/. Review: each quarterly brand audit.
Migration plan, hinted → unhinted
ExampleHow to roll the policy out without a visual-regression scare.
1. Inventory weights; flag the heavily-hinted legacy ones. 2. Pilot: strip + WOFF2 one body weight; visual-diff key pages. 3. Roll out remaining weights in the build pipeline. 4. Keep hinted masters; document the exception path. 5. Announce: 'fonts are now ~12% smaller, rendering unchanged.'
The legacy-Windows exception, split delivery
ExampleWhen a real GDI cohort exists, serve both builds without compromising either.
@font-face { /* modern: stripped + woff2 */
font-family: Brand;
src: url(/fonts/brand.unhinted.woff2) format('woff2');
}
/* legacy UA -> serve /fonts/brand.hinted.woff via UA sniff or
conditional <link>; keep the hinted master to build it. */Apple-only product — unconditional strip
ExampleCoreText never reads TrueType hints, so there's no exception to carve out.
Audience: 100% macOS + iOS. Policy: strip every weight, no legacy exception needed. Pipeline: hinting-stripper -> font-subsetter -> ttf-to-woff2. Result: smaller fonts, pixel-identical rendering.
Quarterly review entry
ExampleKeep the policy defensible with a dated check of the deciding metric.
2026-Q2 review: Win7/8 GDI share: 0.3% (was 0.5% in Q1) — trending down. Decision: policy unchanged, continue stripping. Next review: 2026-Q3.
Edge cases and what actually happens
Every row below was probed against the live API. Some documented requirements (alphabetical axis order, numerical tuple order) are not actually enforced in practice — useful to know if you've been blaming the wrong thing for a 400.
Policy mandates 'strip' but forgets the WOFF2 step
Common mistakeThe strip outputs a raw TTF. A policy that says 'strip all fonts' without mandating re-compression will ship decompressed fonts that are larger than the WOFF2 they replaced. Always pair strip with ttf-to-woff2 in the policy text and the pipeline.
Expecting per-table policy knobs
Not supportedThe tool removes all seven tables with no options. A policy can't say 'keep cvt system-wide' and expect the hosted tool to honour it — that would require a custom CI script. Keep the policy aligned with the tool: all seven, always.
Real legacy-Windows cohort ignored
Audience riskIf your analytics show >5% Windows 7/8 GDI traffic and you strip anyway, those users get softer 10–12px text. The policy should name a threshold and an exception path (split delivery) rather than blanket-stripping for everyone.
OTF assets show no savings
PreservedCFF/OTF fonts have no fpgm/prep/cvt , so stripping them yields 0% and renames them to .ttf. The policy's savings projections should be based on your TrueType faces; OTF weights contribute nothing to the strip line item.
Brand insists hinting is a quality requirement
Context-dependentAt brand sizes (display headings, 24px+) and on 2x displays, hinting is irrelevant to perceived quality — the win there is from outlines and antialiasing, not bytecode. Reframe the conversation around the actual rendering sizes; reserve the keep-hinting exception for genuine small-size legacy cases.
Stale head checksum trips a QA gate
Checksum warningThe strip leaves head.checkSumAdjustment unrecomputed. If your design-system QA runs fontbakery, it may flag this. It's cosmetic for rendering; either whitelist that check or add a fonttools checksum-fix stage to the pipeline.
Variable fonts in the system
SupportedStripping a variable TTF removes its hint tables but keeps fvar/gvar/STAT, so it stays variable — a clean fit for a token-driven system. If the policy also wants static instances for old browsers, that's a separate variable-font-freezer stage, not part of the strip.
No version-controlled hinted master
Operational riskStripping is destructive; if you only keep the stripped output and later need hints back for a legacy audience, you can only re-generate (with ttfautohint), never restore the originals. The policy must require keeping hinted masters in the repo.
Assuming SEO ranks on font crispness
MisconceptionFont rendering quality is not a ranking signal. The SEO effect is indirect and positive: smaller fonts improve LCP/CWV. So the policy's SEO justification should be 'better Core Web Vitals,' not 'sharper text.'
Inconsistent results across weights of one family
ExpectedDifferent weights of the same family can carry different amounts of hinting (the bold might be more heavily hinted than the regular), so per-weight Saved % will vary. That's normal — report the aggregate, not a single per-weight number, in the policy's savings claim.
Frequently asked questions
When is an unhinted policy the wrong default?
When a meaningful share of your audience runs Windows 7/8 GDI — industrial software, older enterprise intranets — and reads text at 10–12px. Above roughly a 5% legacy-GDI share, keep hinting for that cohort. For consumer-facing 2026 products, unhinted is the right default.
Does an unhinted policy affect SEO?
Only indirectly and positively: smaller fonts improve LCP and reduce render-blocking weight, which helps Core Web Vitals. Font rendering crispness isn't a ranking signal, so unhinted fonts don't hurt SEO.
What about brand typography quality at small sizes?
Below ~12px on Windows 7 GDI, unhinted text is slightly softer. On 2x/retina displays and at 14px+, the difference is invisible. Modern brand typography mostly lives at sizes where hinting is irrelevant, so quality holds.
Does the policy need a WOFF2 step?
Yes — non-negotiable. The strip outputs raw TTF, so without a WOFF2 re-compression stage you'd ship larger files than before. Mandate strip → WOFF2 (plus subsetting) as one pipeline.
Can the policy specify keeping certain hint tables?
Not with the hosted tool — it always removes all seven. Selective keeping would require a custom CI script that diverges from the tool. Keep the policy simple and aligned: strip all seven, always.
How do I justify the policy to stakeholders?
With a dated metric: your Windows 7/8 GDI share and a visual-regression result showing no perceptible change for the rest. 'Stripped because legacy-GDI < 1% as of 2026-06, rendering verified unchanged' is a defensible one-liner.
Do OTF fonts benefit from the policy?
Not from the strip — CFF/OTF fonts have no fpgm/prep/cvt , so stripping does nothing but rename them to .ttf. Base your savings estimate on your TrueType faces; OTF weights contribute zero to the strip line.
How do I handle variable fonts under the policy?
Strip them like any TTF — hint tables go, fvar/gvar/STAT stay, the font remains variable. If the policy also wants static fallbacks, add a separate variable-font-freezer stage; instancing isn't part of stripping.
What's the migration risk?
Low for modern audiences, because outlines are untouched — an unhinted build is a drop-in on DirectWrite/CoreText. The only risk is the legacy-GDU cohort, which you handle with the documented exception (split delivery).
Should I keep the original hinted fonts?
Always, in version control. Stripping is destructive; you can re-generate hints later but never restore the originals byte-for-byte. The hinted master is also what you build the legacy-exception variant from.
How often should the policy be reviewed?
Quarterly, or at each brand refresh. The deciding metric — legacy-GDI traffic — only trends down, so reviews mostly confirm the policy. A dated review keeps the decision defensible.
Will validators complain about policy-built fonts?
Possibly about the unrecomputed head.checkSumAdjustment. Renderers ignore it; strict QA (fontbakery) may warn. Either whitelist that check or add a fonttools checksum-fix step to the pipeline.
Privacy first
Every JAD Font tool runs entirely in your browser using opentype.js and the wawoff2 WASM Brotli encoder. Your fonts never leave your device — verified by zero outbound network requests during processing.