fix(web): cut the copy, drop the Product tab, put npm in the header#294
Merged
Conversation
Collaborator
Author
How to use the Graphite Merge QueueAdd either label to this PR to merge it via the merge queue:
You must have a Graphite account in order to use the merge queue. Sign up using this link. An organization admin has enabled the Graphite Merge Queue in this repository. Please do not merge from GitHub as this will restart CI on PRs being processed by the merge queue. This stack of pull requests is managed by Graphite. Learn more about stacking. |
Contributor
Sketchi Web PreviewStatus:
Preview Worker cleanup has completed. |
Contributor
Sketchi Icons PreviewStatus:
Preview Worker cleanup has completed. |
Contributor
Sketchi Excalidraw Workspace PreviewStatus:
Preview Worker cleanup has completed. |
Contributor
Sketchi Eval Harness PreviewStatus:
Preview Worker cleanup has completed. |
Contributor
Sketchi Playground / Studio PreviewStatus:
Preview Worker cleanup has completed. |
Merge activity
|
…294) Subtractive pass over `apps/web`, per the S5 brief. Three jobs plus a full read of the rest of the site. ## 1. Nav — Product removed `{ href: "/#product", label: "Product" }` is gone from the header. The `FeatureGrid` section keeps `id="product"`; nothing else in the repo linked to that anchor (grepped), so no dangling target. ## 2. npm beside GitHub `https://www.npmjs.com/package/sketchi` now sits in the header actions next to GitHub, in the same 40px `.site-header__mark` button with the same hover and focus treatment, and again in the mobile sheet where the desktop actions are hidden. npm now uses its **wordmark**, masked in `currentColor` exactly like `.gh-mark`, at its natural 46×18 rather than forced into a 20px square. It inherits ink on the light header and paper on the dark footer, and appears in the header bar, the mobile sheet, and the footer's More column. Two things about the asset, since neither was obvious: - **The square tile cannot be masked.** `/brand/npm.svg` is a knockout — a solid red 100×100 with the `n` cut out — so an alpha mask renders the complement: a bare frame with a bar in it. Shipping it in colour instead (the first push) read as a red blob, not as npm, and broke the header's monochrome treatment. - **npm's wordmark geometry cannot be masked verbatim either.** Its letters bleed to the left, top, and right edges of the red box, so the holes break the field's outline and the mask renders as disconnected slivers. `/brand/npm-wordmark.svg` therefore uses npm's own 780×250 letter grid **unchanged**, inset by a uniform 50 units. That inset is the only deviation and it is load-bearing. The footer's "npm package" entry takes the same mark, which drops two words — the wordmark is the word. ## 3. Every string deleted **CLI band** - "`sketchi` is a real command-line tool, not a wrapper around this website. It keeps your diagrams in `~/.sketchi/diagrams`, does its authoring, export, and recovery work offline, and speaks `--output json` on every command so an agent can drive it." - "Generate without signing in" - "One prompt, one HTTPS request, a validated diagram on disk. No API key, token, or account." - "Seven commands work offline" - "Create, patch, show, edit, list, export, and restore never touch the network or a model." - "Export from the terminal" - "Render PNG or Excalidraw locally, deterministically, without starting a browser." - "Installs the package and sets up completions for zsh, bash, or fish." - "Straight from npm, if you would rather configure completions yourself." - "Then ask for a diagram:" - "Read the CLI docs →" Replaced by one line: "`sketchi` draws diagrams from your shell. No account, no API key, and `--output json` on every command so an agent can drive it." **Feature grid** — the three sentences added in an earlier round: - "Every shape, connector, and label stays editable after generation." - "Find the tools in your stack without drawing their marks by hand." - "Open the scene in Excalidraw, then export it when you are ready." Nothing replaces them. The band was thin without them, so the cards got a surface, padding, and a tighter grid — layout, not words. **Closing CTA** - "or install the CLI →" **Footer** - "Prompts become real, editable diagrams, logos included." - "Made for people who'd rather describe a diagram than draw one." - "npm package" (the wordmark says it) Both restated the hero. The hero survives. **Docs** - "You describe it." (from the Three paths lead) - ", not a best-guess sketch" - ", so nothing you make is trapped in a browser tab" - "Makes a single credential-free HTTPS request — " → "No key, token, account, or login." - "PNG rendering is deterministic and local; it never starts a browser or uses the network." → "Local and deterministic; never uses the network." - "Read the code, file an issue, or run your own copy." - "Take it to your docs, slides, or pull request." → "Yes, as PNG or Excalidraw." - both install captions (shared with the CLI band above) **Agents (hub + all four pages)** - ", not a wall of ASCII" - "Add this URL wherever your agent keeps its MCP config." (endpoint caption, hub) - "Public endpoint used by the setup below." (endpoint caption, detail pages) - "Installs as a Codex plugin, so the skill is always a command away." - "Setup is just the skill plus the public MCP server." (×2) - "The plugin bundles the skill, so you can ask in plain language." - "; provider and model behavior remain OpenCode concerns" - "; model and harness behavior remain Agy concerns" Kept: "No account, API key, or local browser needed." on each page, and Antigravity's merge-don't-overwrite note, which is real setup information the heading does not carry. **Dead code removed with it:** `cliCapabilities`, `CliCapability`, `CliInstallOption.detail`, `CtaBandProps.cliHref`, `CliBandProps.docsHref`, `SiteFooterProps.colophon`, `EndpointCard`'s `meta` prop, and the CSS for `.cli-band__points`, `.cli-band__point`, `.cli-band__note`, `.cli-band__then`, `.cli-band__step`, `.cli-band__docs-link`, `.feature-card__description`, `.site-footer__tagline`, `.agent-endpoint__meta`. No caption, tooltip, helper line, or "learn more" was added anywhere. Install commands are byte-identical — `cli-package.test.ts` still pins them. ## Tests Rewritten to assert the absence rather than deleted: the CLI band now proves it makes *no* offline claim and captions nothing; the feature grid proves no `<p>` under a title; the CTA proves two actions; the footer proves the hero thesis is not restated; the header proves both marks reach the mobile sheet. ## Proof - `pnpm nx run-many -t typecheck,test,build` — green (52 tasks) - `pnpm test:tools` — 64 passed - Real Chrome at 1440×900 and 390×844: home, `/docs`, `/agents`, `/agents/codex`, `/agents/antigravity`. npm and GitHub both link correctly in the bar and the sheet, no Product tab, no empty container or dangling anchor from anything cut. - Both marks checked at 1x on the light header, the dark footer, and in the mobile sheet. - `codex review --base main` — clean on both pushes.
graphite-app
Bot
force-pushed
the
fix/declutter-web
branch
from
July 25, 2026 17:21
42c78e4 to
ca6b91d
Compare
graphite-app Bot
pushed a commit
that referenced
this pull request
Jul 25, 2026
## Why
Dancing Script is the default Google handwriting face — it reads as picked from a dropdown. Excalifont is the exact typeface every Sketchi diagram renders in, so the wordmark stops being decoration and becomes an instance of the product: the name written in the same hand the product draws.
On the playground the wordmark now sits inches from `GitHub push` / `Docker build` / `Run tests` in the same face. That adjacency is the whole point of the change.
## Licence finding
**Excalifont is SIL Open Font License 1.1, and OFL explicitly permits this use.** Verified rather than assumed:
- The vendored files are byte-identical to `excalidraw/excalidraw@master`. The `woff2` name table carries the copyright but **no** licence fields (nameID 13/14 absent), so the licence comes from upstream's `fonts/Excalifont/index.ts` metadata block (`"This Font Software is licensed under the SIL Open Font License, Version 1.1"`) and from `plus.excalidraw.com/excalifont` ("Released under the OFL-1.1 license ... freely available for both personal and commercial use").
- Wordmark use is squarely allowed. OFL clause 5 exempts "any document created using the Font Software", and the OFL FAQ 1.1/1.1.1 answers the logo question directly: *"Can I use the fonts ... to create logos or other graphics ... Yes."* and *"You remain the author and copyright holder of that newly derived graphic."* So the Sketchi wordmark stays ours; no copyleft reaches it.
- **No Reserved Font Name is declared**, so even naming restrictions on derivatives don't bite. We make no derivative regardless.
- Two obligations do apply, and both are now met:
1. Clause 2 — the copyright notice and licence must travel with every redistributed copy. Serving `woff2` from our origins is redistribution, so a `LICENSE` now sits beside the files in every `public/fonts/Excalifont`. Previously the playground served them with no notice at all.
2. Trademark — upstream declares *"Excalifont is a trademark of Excalidraw."* We use the letterforms, never the name, as Sketchi branding. The CLI's `THIRD_PARTY_NOTICES` was missing this line and now carries it.
No blocker. Ship it.
## Legibility pass
Checked in a real browser at every size the wordmark actually appears, on both paper and reversed out of dark ink.
**One adjustment was needed, and it was the important one: every placement drops from `font-weight: 700` to `400`.** Excalifont ships Regular only, so 600/700 was Chrome synthesising the weight — strokes thicken without the letters widening and the counters in `e`/`c` close up, exactly the "turns to mush" failure mode for a hand-drawn face. Regular is the real hand.
**No size changes were needed.** Measured against the outgoing face at 28px, Excalifont is ~12% wider with a taller cap (20 vs 18) but a slightly *smaller* x-height (12 vs 13) — so shrinking it to preserve the old footprint would have made it less legible, not more. At the three real sizes (28px header/playground, 26px dark footer, 25px icons narrow) the counters stay open and reversed strokes don't bloom.
The 404s on all three surfaces turned out to carry no wordmark at all — they're display-font headings only, so there was nothing to adjust there.
## What changed
- `--font-script` in `theme.css` drives everything, so the swap is one token plus the `@font-face` set beside it. All seven cn-font-split subsets are declared with their upstream `unicode-range` — they're subsets of one face, not seven faces, so declaring only the Latin one leaves every other codepoint silently falling back.
- Fonts vendored per surface (each Worker serves its own `public/`), with `diagram-ui` holding the reference copy and serving it to Storybook via `staticDirs`. `tools/vendored-excalifont.test.ts` pins all six copies byte-identical and derives the surface list from the theme imports, so a new theme consumer fails the test instead of shipping a 404 for its own brand face.
- Surfaces that draw the wordmark preload the Latin subset, so the lockup paints in Excalifont rather than reflowing through the sans.
- The og:card — the most-seen wordmark instance of all — is a static PNG a token can't reach. Its wordmark and `yes`/`no` tags are now Excalifont outlines rather than `<text>`, so it doesn't depend on a webfont reaching whichever renderer rasterises it (and outlines are the cleaner licence position: a document, not the font).
- Dancing Script is now unreferenced and leaves every Google Fonts URL.
Kept off `site-header.tsx` and all copy for the parallel declutter agent.
## Proof
- `pnpm nx run-many -t typecheck,test,build` — green (52 tasks)
- `pnpm nx build-storybook diagram-ui` — green
- `pnpm test:tools` — green (82 tests; `run-many` does not cover this)
- `pnpm lint` — green
- Verified in Chrome on web, icons, playground, excalidraw and Storybook: font 200s, `0` errored faces, wordmark computed at `400`, plus the three 404s and the icons narrow breakpoint. Build outputs confirmed to ship the subsets on all five surfaces.
- `codex review --base main` — clean on the third pass. It found two real defects I'd missed: 404ing font URLs on the two theme consumers that don't draw a wordmark, and the stale Dancing Script social card. Both fixed here.
## Rebase onto #294
Rebased onto `ca6b91d` (Product tab dropped, npm mark added, copy cut) and the legibility pass was re-run against the header that will actually ship, not the stale one: wordmark computed `28px`/`400`, `0` errored faces, no overflow at 390px, dark footer and 404 re-checked, and the fresh preview confirms the new three-item nav. The looser nav actually gives the lockup more room than before.
On the three visual languages now in one bar: the wordmark is not the friction — it's ink-toned text that belongs to the same layer as the nav, and the tile+wordmark lockup is separated from the utility cluster by the whole nav. The friction is the **npm mark**, for three reasons: it is the only filled container in the bar besides the Playground CTA (so it reads as a competing button immediately left of the real one), it is the highest-contrast, only-square-cornered element in a system that is otherwise rounded ink-on-paper, and it is optically much heavier than the Octocat sitting next to it, so two same-tier utility links read at different volumes. Recommendation is to render npm as a bare monochrome wordmark in `--ink-2`, matched to the Octocat's cap height, with no filled block — that makes GitHub+npm a coherent quiet pair and gives the CTA back its status as the only filled element. Not changed here: those marks landed in #294 and are not this PR's scope.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

Subtractive pass over
apps/web, per the S5 brief. Three jobs plus a full read of the rest of the site.1. Nav — Product removed
{ href: "/#product", label: "Product" }is gone from the header. TheFeatureGridsection keepsid="product"; nothing else in the repo linked to that anchor (grepped), so no dangling target.2. npm beside GitHub
https://www.npmjs.com/package/sketchinow sits in the header actions next to GitHub, in the same 40px.site-header__markbutton with the same hover and focus treatment, and again in the mobile sheet where the desktop actions are hidden.npm now uses its wordmark, masked in
currentColorexactly like.gh-mark, at its natural 46×18 rather than forced into a 20px square. It inherits ink on the light header and paper on the dark footer, and appears in the header bar, the mobile sheet, and the footer's More column.Two things about the asset, since neither was obvious:
/brand/npm.svgis a knockout — a solid red 100×100 with thencut out — so an alpha mask renders the complement: a bare frame with a bar in it. Shipping it in colour instead (the first push) read as a red blob, not as npm, and broke the header's monochrome treatment./brand/npm-wordmark.svgtherefore uses npm's own 780×250 letter grid unchanged, inset by a uniform 50 units. That inset is the only deviation and it is load-bearing.The footer's "npm package" entry takes the same mark, which drops two words — the wordmark is the word.
3. Every string deleted
CLI band
sketchiis a real command-line tool, not a wrapper around this website. It keeps your diagrams in~/.sketchi/diagrams, does its authoring, export, and recovery work offline, and speaks--output jsonon every command so an agent can drive it."Replaced by one line: "
sketchidraws diagrams from your shell. No account, no API key, and--output jsonon every command so an agent can drive it."Feature grid — the three sentences added in an earlier round:
Nothing replaces them. The band was thin without them, so the cards got a surface, padding, and a tighter grid — layout, not words.
Closing CTA
Footer
Both restated the hero. The hero survives.
Docs
Agents (hub + all four pages)
Kept: "No account, API key, or local browser needed." on each page, and Antigravity's merge-don't-overwrite note, which is real setup information the heading does not carry.
Dead code removed with it:
cliCapabilities,CliCapability,CliInstallOption.detail,CtaBandProps.cliHref,CliBandProps.docsHref,SiteFooterProps.colophon,EndpointCard'smetaprop, and the CSS for.cli-band__points,.cli-band__point,.cli-band__note,.cli-band__then,.cli-band__step,.cli-band__docs-link,.feature-card__description,.site-footer__tagline,.agent-endpoint__meta.No caption, tooltip, helper line, or "learn more" was added anywhere. Install commands are byte-identical —
cli-package.test.tsstill pins them.Tests
Rewritten to assert the absence rather than deleted: the CLI band now proves it makes no offline claim and captions nothing; the feature grid proves no
<p>under a title; the CTA proves two actions; the footer proves the hero thesis is not restated; the header proves both marks reach the mobile sheet.Proof
pnpm nx run-many -t typecheck,test,build— green (52 tasks)pnpm test:tools— 64 passed/docs,/agents,/agents/codex,/agents/antigravity. npm and GitHub both link correctly in the bar and the sheet, no Product tab, no empty container or dangling anchor from anything cut.codex review --base main— clean on both pushes.