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

418 lines
16 KiB
Markdown

# 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:
```bash
curl -s https://design-system.hpe.design/foundation/color | wc -c
# 1540
```
There is also no sitemap and no robots.txt. Both 404:
```bash
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:
```bash
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.
```bash
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:
```bash
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`:
```bash
#!/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
```
```bash
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:
```bash
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`:
```python
#!/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:
```bash
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)
```bash
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:
```bash
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
```bash
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)
```bash
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](https://www.hpe.com/us/en/about/legal/terms-of-use.html),
with authoritative files and usage rules on
[Brand Central](https://brandcentral.hpe.com/home) (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.
## Recommended output shape
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 |