Files
hpe-branding/HOWTO-mirror-the-design-system.md
T
claude 0730557624 Initial mirror of the HPE Design System
Readable mirror of https://design-system.hpe.design, sourced from
github.com/grommet/hpe-design-system (Apache-2.0) at commit 567c4d5
(2026-07-16).

The upstream site is a client-rendered Next.js export with no sitemap; it
returns a 1.5 KB empty shell to curl. This repo is the same guidance in plain
Markdown with every value resolved, plus the assets checked in.

Docs: scope and authority model, brand foundations with resolved color and
spacing tables, the design token tiers and version map, UI copy rules,
accessibility conformance and the responsibility split, the component and
template inventory, and an adoption/review checklist.

Assets: 452 SVG icons, 5 HPE and Aruba word-marks, 282 documentation graphics.

HOWTO-mirror-the-design-system.md is a verified runbook for rebuilding this
from scratch against a newer upstream.

Colors were resolved programmatically, not transcribed: token JSON stores
references, not values.

Apache-2.0 upstream. Note that it covers copyright, not trademark; Brand
Central remains authoritative for the HPE marks.
2026-07-30 08:34:50 -04:00

16 KiB

How to mirror the HPE Design System

A runbook for reproducing everything in this folder: the guidance docs, the 452-icon set, the brand marks, and all 282 documentation graphics.

Written to be handed to someone else and followed start to finish, by a person or by an AI coding agent. Every command below was run and verified on 2026-07-30. Nothing here needs an HPE login, a VPN, or a token.

Total time: about ten minutes, most of it the clone.


The problem you will hit first

https://design-system.hpe.design looks like a normal documentation site. It is not scrapeable.

It is a Next.js static export that renders entirely in the browser. Fetch any page and you get a 1.5 KB HTML shell with zero content:

curl -s https://design-system.hpe.design/foundation/color | wc -c
# 1540

There is also no sitemap and no robots.txt. Both 404:

curl -s -o /dev/null -w '%{http_code}\n' https://design-system.hpe.design/sitemap.xml   # 404
curl -s -o /dev/null -w '%{http_code}\n' https://design-system.hpe.design/robots.txt    # 404

The Next.js data endpoint does not help either. The pages are autoExport with empty pageProps, so /_next/data/<buildId>/<route>.json returns 404. The content is compiled into JavaScript chunks.

Do not try to scrape the site. Do not reach for a headless browser. There is a much better source.

The key insight

The whole design system is open source:

https://github.com/grommet/hpe-design-system — Apache-2.0

Every page on that site is an MDX file in that repo. The icons, the graphics, and the raw design token JSON are in there too. Clone it and you have everything, in a form that greps.

Find it yourself with:

curl -s "https://api.github.com/search/repositories?q=hpe-design-system" \
  | grep -E '"full_name"|"html_url"'

Step 1 — Clone

Shallow clone. Full history is not needed and is much larger.

git clone --depth 1 https://github.com/grommet/hpe-design-system.git hpeds
cd hpeds
git log -1 --format='%H %cI %s'   # record this SHA for provenance
du -sh .                          # ~81 MB

Record the commit SHA. Version numbers in the docs move; citing a SHA makes your notes checkable later. The mirror in this folder was taken at 567c4d5 (2026-07-16).

Do not run pnpm install. Nothing here needs a build.

Step 2 — Know the layout

hpeds/
├── apps/
│   ├── docs/
│   │   ├── src/pages/          <- ALL documentation content, as .mdx
│   │   └── public/             <- ALL graphics (282 files, 32 MB)
│   └── design-tokens-manager/
├── packages/
│   ├── hpe-design-tokens/
│   │   └── tokens/             <- raw token JSON (primitive/semantic/component)
│   ├── icons-svg/src/icons/    <- 452 raw SVG icons
│   ├── icons-grommet/          <- the same icons as React components
│   └── codemods/
├── knowledge/                  <- their own AI agent capability bundles
└── LICENSE                     <- Apache-2.0

Content page counts, so you know when you have it all:

find apps/docs/src/pages -name '*.mdx' | wc -l   # 112
for d in foundation design-tokens components templates learn; do
  printf '%-16s %s\n' "$d" "$(find apps/docs/src/pages/$d -name '*.mdx' | wc -l)"
done
# foundation       20
# design-tokens    11
# components       49   (48 component pages + an all-components index)
# templates        27
# learn             4

Those five directories account for 111. The 112th is whats-new.mdx at the page root. Widening the search to apps/docs -type f \( -name '*.mdx' -o -name '*.md' \) returns 117, because it picks up repo READMEs outside the page tree. Use the narrower count when checking coverage.

Step 3 — Get the full route list

Useful as a checklist to confirm you covered everything. The site is a Next.js export, so its build manifest lists every route.

The build ID changes on every redeploy, so extract it rather than hardcoding it. Save as routes.sh:

#!/usr/bin/env bash
# Extract every route from the HPE Design System site (Next.js static export).
set -euo pipefail
UA="Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0 Safari/537.36"
BASE="https://design-system.hpe.design"
BUILD_ID=$(curl -sS -A "$UA" "$BASE/" \
  | grep -oE '/_next/static/[A-Za-z0-9_-]{16,}/_buildManifest\.js' | head -1)
echo "buildManifest: $BUILD_ID" >&2
curl -sS -A "$UA" "$BASE$BUILD_ID" \
  | tr ',' '\n' | grep -oE '"/[^"]*"' | tr -d '"' | sort -u
chmod +x routes.sh && ./routes.sh | wc -l   # 123

Step 4 — Read the content

The MDX files are prose plus JSX examples. Read the prose; the <Example> and <BestPracticeGroup> tags import React components from apps/docs/src/examples/ and can be ignored unless you need a rendered figure.

Priority order, highest value first:

File Why
foundation/voice-and-tone.mdx 55 KB, the largest doc on the site. UI copy rules
foundation/accessibility.mdx 18 KB. WCAG level, responsibility split table
foundation/date-and-time.mdx 15 KB
foundation/typography.mdx Font CDN URLs, heading rules
foundation/color.mdx The eight color families and their jobs
foundation/our-brand.mdx Logo and Element placement rules
foundation/distinctive-brand-assets.mdx GreenLake badge status
design-tokens/overview.mdx The three-tier token model
design-tokens/versioning.mdx Version-to-theme map, migration paths
foundation/philosophy-and-principles.mdx The three pillars, four principles

Sort the rest by size to prioritize:

wc -c apps/docs/src/pages/foundation/*.mdx apps/docs/src/pages/design-tokens/*.mdx | sort -n

Raw single-file access without cloning, if you only want one page:

https://raw.githubusercontent.com/grommet/hpe-design-system/master/apps/docs/src/pages/foundation/color.mdx

Step 5 — Resolve design tokens to real values

This is the part worth automating, and the part most likely to be got wrong.

Token JSON does not contain values. It contains references. A semantic token points at a primitive, which may point at another primitive. Reading color.light.json directly gives you {base.color.grey.50}, not #f7f7f7.

Two more traps:

  1. Semantic tokens carry a .REST suffix on the leaf that references often omit, so a naive lookup misses.
  2. There is a deprecated.* namespace holding superseded values. A stale reference resolves to a visibly different color: deprecated.base.color.green.400 is #17eba0 where the live base.color.green.400 is #00e0af.

Save as resolve-tokens.py:

#!/usr/bin/env python3
"""Resolve HPE design tokens to concrete values.

Usage: resolve-tokens.py <repo-root> [filter-substring]
Tokens are stored as {references}; this follows them to real hex/number values.
"""
import json, sys, os

root = sys.argv[1]
needle = sys.argv[2] if len(sys.argv) > 2 else ''
T = os.path.join(root, 'packages/hpe-design-tokens/tokens')

def flat(o, p=''):
    out = {}
    if isinstance(o, dict):
        if '$value' in o:
            return {p: o['$value']}
        for k, v in o.items():
            out.update(flat(v, f'{p}.{k}' if p else k))
    return out

prim  = flat(json.load(open(f'{T}/primitive/primitives.default.json')))
light = flat(json.load(open(f'{T}/semantic/color.light.json')))
dark  = flat(json.load(open(f'{T}/semantic/color.dark.json')))

def resolve(v, tbl, depth=0):
    while isinstance(v, str) and v.startswith('{') and depth < 10:
        k = v.strip('{}')
        v = prim.get(k, tbl.get(k + '.REST', tbl.get(k)))
        depth += 1
    return v

for k in sorted(light):
    if needle and needle not in k:
        continue
    print(f'{k:52} light={str(resolve(light[k], light)):12} dark={resolve(dark.get(k), dark)}')

Run it:

python3 resolve-tokens.py hpeds 'text.'
# color.text.default.REST      light=#3e4550   dark=#e6e8e9
# color.text.heading...REST    light=#292d3a   dark=#ffffff
# color.text.critical...REST   light=#cc1f1a   dark=#ff7b7b

python3 resolve-tokens.py hpeds 'background.'
python3 resolve-tokens.py hpeds ''            # everything, 108 semantic color tokens

The units gotcha

Dimension primitives are stored as unitless numbers. base.dimension.400 is the number 16, not "16px". Units are applied at build time by packages/hpe-design-tokens/src/transforms/numberToDimension.ts, and not uniformly:

  • fontSize and lineHeight are divided by 16 and emitted as rem
  • everything else (spacing, radius, padding, width, height, border width, breakpoints) is emitted as px

If you report a raw number as a pixel value for a font size, you will be wrong by a factor of 16.

Step 6 — Pull the assets

Icons (452 SVGs, 1.9 MB)

mkdir -p out/icons
cp hpeds/packages/icons-svg/src/icons/*.svg out/icons/
cp hpeds/packages/icons-svg/LICENSE hpeds/packages/icons-svg/COPYRIGHT.md out/icons/
ls out/icons/*.svg | wc -l   # 452

Properties, verified:

grep -ho 'viewBox="[^"]*"' out/icons/*.svg | sort | uniq -c | sort -rn
#  448 viewBox="0 0 24 24"
#    2 viewBox="0 0 24 25"     (catalog.svg, chat.svg)
#    1 viewBox="0 0 48 24"     (element.svg)
#    1 viewBox="0 0 24 26"     (chat-conversation.svg)

grep -l 'currentColor' out/icons/*.svg | wc -l   # 451 of 452
grep -ho 'fill="#[0-9A-Fa-f]*"' out/icons/*.svg | sort | uniq -c
#    1 fill="#01A982"          (element.svg only)

The HPE Element is icons/element.svg, not a logo file. It is the one icon with a hardcoded color, because the brand green must not inherit from its container.

Brand marks

mkdir -p out/brand
cp hpeds/apps/docs/public/HPE_logo_full-clr_{pos,rev}_rgb.svg out/brand/
cp hpeds/apps/docs/public/static/images/{hpe-logo,hpe-logo-invert,aruba-logo}.svg out/brand/

All documentation graphics (282 files, 32 MB)

mkdir -p out/site-images
cp -r hpeds/apps/docs/public/. out/site-images/
find out/site-images -type f | wc -l   # 282

Two things to know before you commit 32 MB:

  • About 14 MB is Unsplash stock photography in learnImages/grid-fundamentals-part-1/: four JPGs between 2.5 and 4.9 MB used as filler in a Grommet grid tutorial. No HPE guidance in them. Drop that one folder and you reclaim nearly half the total.
  • logos/ holds partner logos, not HPE marks (Apache, Dataiku, Dremio, H2O, SingleStore, StreamSets and others). Third-party trademarks, not covered by this repo's Apache-2.0 license. Do not mix them into a brand folder.

Step 7 — Verify before you trust it

Do not skip this. Several claims that look obvious are wrong.

Verify color claims programmatically rather than reading them off a page. Every color value in this folder's docs was checked by resolving the token reference chain and diffing against the written claim. Three examples that catch people out:

  • HPE green #01a982 is color.decorative.brand, not the primary action color. Primary interactive surfaces use #068667 in light mode and #05cc93 in dark. Calling a button "HPE green" and reaching for #01a982 produces the wrong button.
  • base.color.green.400 and base.color.green.500 are both #00e0af. That looks like a bug in your parser. It is not; the source really has both.
  • color.background.front is #ffffff in light mode and #292d3a in dark, while color.text.strong is #292d3a in light. The same hex serves opposite roles across modes. Do not deduplicate by value.

Check the docs against themselves. The accessibility page cites WCAG 2.2 at the top and WCAG 2.1 in its government-standards section. The conformance level is consistent (A and AA required, per: "The guidelines identified as level A and AA are the required design elements for all applications") but the version reference is not. Record the discrepancy rather than picking one silently.

Do not infer from filenames. The repo has a knowledge/capabilities/ alignment-audit/ entry that sounds like a product compliance audit. Reading it shows a planned stub scoped to auditing the design system's own docs and tokens. Only docs-refactor is marked active. Open the file.

Step 8 — Currency

Two traps when judging how current something is:

  • The site's "What's new" page is stale. Its most recent entry is April 2023. It is not a changelog.
  • Use these instead:
    • packages/hpe-design-tokens/CHANGELOG.md
    • GitHub releases on grommet/hpe-design-system
    • apps/docs/src/pages/design-tokens/versioning.mdx for the version-to-theme map

As of 2026-07-30: hpe-design-tokens 2.2.3, @hpe-design/icons-grommet 1.2.0, @hpe-design/icons-svg 0.2.0. Current theme generation is v2-Landmark (October 2025 onward), paired with grommet-theme-hpe 8.x.

Licensing, and the one thing to be careful about

The repo is Apache-2.0, "Copyright 2025 Hewlett Packard Enterprise Development LP." Copying the content and assets into an internal knowledge repo is fine, with attribution.

An open-source copyright license grants no trademark rights. The HPE logo and the Element are HPE trademarks. Their use is governed by the HPE Terms of Use, with authoritative files and usage rules on Brand Central (HPE login required).

Practical consequence: a vendored logo is fine for reading and internal reference, but pull the current file from Brand Central for anything that ships or reaches a customer. A vendored mark goes stale silently, and the pending HPE GreenLake rebrand is exactly the event that would make a copy wrong.

Also worth flagging to whoever consumes your mirror: Brand Central and the Design System deliberately disagree on color. The Design System says so directly and instructs product teams to prefer its palette for app and web work. Brand Central governs logos, print, and marketing.

What this folder settled on, if it is useful as a template:

hpe-branding/
├── README.md                          index, provenance, currency traps
├── HOWTO-mirror-the-design-system.md  this file
├── 01-what-it-is.md                   scope, packages, authority model
├── 02-brand-foundations.md            logo rules, resolved hex tables, spacing px
├── 03-design-tokens.md                three tiers, version map, units
├── 04-voice-and-tone.md               UI copy rules, term list
├── 05-accessibility.md                conformance level, responsibility split
├── 06-components-templates.md         48 components, 27 templates
├── 07-adoption-and-compliance.md      adoption paths, review checklist
└── assets/
    ├── icons/        452 SVGs + LICENSE
    ├── brand/        5 word-marks
    └── site-images/  282 documentation graphics

The judgment call worth repeating: write down the resolved values, not just links to the site. The whole reason this is work is that the site cannot be read without a browser. A mirror that only links back to it solves nothing.

Quick reference

Thing Where
Docs site https://design-system.hpe.design (browser only)
Source repo https://github.com/grommet/hpe-design-system (Apache-2.0)
MDX content apps/docs/src/pages/**/*.mdx
Graphics apps/docs/public/
Raw icons packages/icons-svg/src/icons/
Token JSON packages/hpe-design-tokens/tokens/
Grommet theme https://github.com/grommet/grommet-theme-hpe
Component props https://v2.grommet.io/<component>?theme=hpe
Icon Storybook https://hpe-design-icons-grommet.netlify.app/
Brand Central https://brandcentral.hpe.com/home (HPE login)
Slack #hpe-design-system on grommet.slack.com and HPE enterprise Slack