Skip to main content
ClaudeWave
Skill1.9k repo starsupdated 3d ago

web-design

Penguin visual language for generated web pages and app UIs — GitHub-style simplicity with a single blue accent, light and pure-black dark themes, design tokens, component and chat-interface recipes, plus an opt-in warm paper editorial theme.

Install in Claude Code
Copy
git clone --depth 1 https://github.com/Prism-Shadow/penguin-harness /tmp/web-design && cp -r /tmp/web-design/packages/skills/skills/web-design ~/.claude/skills/web-design
Then start a new Claude Code session; the skill loads automatically.

SKILL.md

# Web Design

Default visual language for every web page or frontend you generate, distilled from the Penguin Harness landing page and web app. The idea is **GitHub-style simplicity**: solid backgrounds, 1px borders instead of shadows, system fonts, one blue accent used sparingly. Depth comes from hairline borders, not shadows or gradients; dark mode is pure black, not navy. Apply these defaults unless the user explicitly asks for another style. One packaged alternative exists — the **paper editorial** theme below, for requests that call for a warm, print-like feel; pick one language per product and never mix them. The typography discipline, language, motion, IME, citation and responsiveness rules apply under both. Treat the user's one-line request as the whole spec: this skill fills every unstated gap, so the result is a finished page — never a wireframe that waits for styling feedback.

## Before you start

If the user's message only invokes this skill (e.g. "use web-design skill") without a concrete page or interface to build, ask what they want to build. When a concrete build is already requested (an app UI, a landing page, a RAG chat interface), do **not** ask about styling — colors, fonts, spacing, radii and layout are all decided by the defaults below; the only question ever worth asking is *what to build*, never *how it should look*. Route by request shape: conversational or docs-QA → the chat/RAG layout; product or marketing → the page layout; tool-like apps → a sticky nav + panels composed from the components.

Non-negotiable for ANY text input that sends on Enter: **never send while an IME composition is in progress** (check `event.isComposing`, falling back to `event.keyCode === 229`, on keydown). For Chinese/Japanese/Korean input methods, that Enter only confirms the composed text — auto-sending on it fires half-typed messages. Details in the composer recipe below.

## Ship complete

Every delivery, even from a one-line request, includes all of this unasked:

- `<html lang>` matching the UI language; `<meta name="viewport" content="width=device-width, initial-scale=1">`; a real `<title>`.
- Dark mode wired and persisted when using the default language (the paper theme is light-only); single column under 640px; no horizontal scroll.
- Every async surface has designed loading, empty, error and success states — never a blank region or a silent failure.
- A working keyboard path: visible `:focus-visible`, Esc closes overlays (focus returning to the trigger), Enter submits (IME-safe as above).
- `alt` text on images, `aria-label` on icon-only buttons; tap targets ≥ 40px.
- Zero external requests: system fonts, inline or local CSS/JS, inline SVG icons — no CDN, no icon font, no analytics.

## Design tokens

```css
:root {
  color-scheme: light;
  /* Brand blue — the only accent family. Use sparingly: links, eyebrows, tiny dots, tints. */
  --brand-50: #e8f0fe; --brand-100: #d2e3fc; --brand-300: #8ab4f8; --brand-500: #4285f4;
  --brand-600: #1a73e8; /* accent text/icons in light mode */ --brand-700: #0b57d0; /* links on white */
  /* Neutrals (Tailwind gray) */
  --gray-50: #f9fafb; --gray-100: #f3f4f6; --gray-200: #e5e7eb; --gray-300: #d1d5db;
  --gray-400: #9ca3af; --gray-500: #6b7280; --gray-600: #4b5563; --gray-900: #111827;
  --bg: #ffffff; --surface: #ffffff; --border: var(--gray-200); --control-border: var(--gray-300);
  --fg: var(--gray-900); --fg-muted: var(--gray-600); --fg-faint: var(--gray-500);
  --accent-bg: #111827; --accent-fg: #ffffff; /* primary buttons are near-black, not blue */
  --radius-control: 6px; /* buttons, inputs, chips */ --radius-card: 12px; /* cards, panels */
  --ease: cubic-bezier(0.2, 0.7, 0.3, 1);
}
.dark {
  color-scheme: dark; /* pure black, no blue tint */
  --bg: #000000; --surface: #0d0d0d; --border: #1f1f1f; --control-border: #303030;
  --fg: #f3f4f6; --fg-muted: #9ca3af; --fg-faint: #6b7280;
  --accent-bg: #f3f4f6; --accent-fg: #111827; /* primary button inverts to light */
  --brand-600: #8ab4f8; --brand-700: #8ab4f8; /* brand text flips to the 300 tone */
}
```

- Toggle dark mode with a `dark` class on `<html>` (persist the choice; default to `prefers-color-scheme`).
- Primary buttons are **neutral black/white**, never blue fills. Brand blue is reserved for accents: links, section eyebrows, small status dots, `--brand-50` tinted chips.
- Pills, badges and dots use `border-radius: 9999px`; everything else uses the two radii above. No gradients or elevation shadows on content (modals excepted; flat focus rings drawn with `box-shadow` are fine).

## Typography

System fonts only — no CDN fonts, no @font-face. The CJK entries matter (bilingual product):

```css
body { font-family: ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto,
       "PingFang SC", "Microsoft YaHei", sans-serif; -webkit-font-smoothing: antialiased; }
code, pre, kbd { font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; }
```

Headings are always `font-weight: 600` with `letter-spacing: -0.025em` — nothing heavier, no thin weights. Scale: page/hero title 30–36px; section title 24–30px; card title 16–18px; body 14px / line-height 1.5; captions 12px in `--fg-faint`; code 13px / line-height 1.85. Hierarchy comes from weight, size, spacing and hairlines — never from colored blocks.

## Language

Write the page's UI copy in the language the user's request was made in — a Chinese request gets a Chinese interface, an English request an English one — and set `<html lang>` to match. Code identifiers, CSS class names and code comments stay English.

## Components

- **Primary button** — `background: var(--accent-bg); color: var(--accent-fg); border-radius: 6px; padding: 6px 12px; font-size: 14px; font-weight: 500;` hover: `opacity: .9`. Large CTA variant: height 44px, radius 8px, padding 0 20px.
- **Secondary button** — white/`--surface` bg, `1px solid var(--control-border)`, same paddings; hover swaps bg to `--gray-100`/dark `#1f1f1f`.
- **Card** — `b