Communitygithub.com

sayuriovo/terrain-ui

Build web UI in a quiet industrial style distilled from game-menu conventions (paper and ink, one accent for "current" and "primary", selection that reads at a glance, pill secondary buttons, `//` path titles, faint closed contour lines). Use when asked for a page, portfolio, dashboard or component in this style, or in an "industrial", "terminal-like", "Endfield-inspired" or 终末地风格 look.

What is terrain-ui?

Terrain UI is an AI agent skill that provides a set of eight design rules and accompanying CSS/JS assets for building web interfaces with a distinctive, understated industrial aesthetic. Inspired by the UI conventions of an industrial-themed game, it is designed for developers and designers using AI coding agents (such as Claude Code, Cursor, or Codex) to quickly generate pages, portfolios, dashboards, or components. The skill enforces a strict visual system: a single accent color (default `#FEEC00`) for indicating current state and primary actions, selection styles that vary by layout orientation (vertical lists vs. horizontal tabs), button shapes that communicate priority (block primary vs. pill secondary), and a consistent `//` path title at the top of every page. It supports all components needed for modern UIs (tables, forms, dialogs, toasts, etc.) through a utility-class library in `assets/terrain.css` and provides a contour-line background via `assets/contours.js`. The skill emphasizes authenticity—numbers must be real, and product descriptions must be sourced from the user's input—and prohibits the use of game assets, frosted glass, glitch effects, or red-colored error states. It includes clear motion guidelines and a delivery checklist for producing single HTML files that work offline.

Works with~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/sayuriovo/terrain-ui/tree/HEAD

Ask in your favorite AI

Open a new chat with this agent skill pre-loaded.

Documentation

Terrain UI

These rules were distilled from the interface of an industrial-themed game, keeping only what proved useful on ordinary web pages. The skill contains no game assets and does not try to recreate the game.

Read this whole file before you start. Open assets/terrain.css for colors and component markup, use assets/contours.js for the contour background, and see references/research.md for where each rule came from and why some things were left out.

Eight rules

  1. One accent color, two meanings: the current location and the primary action. Default #FEEC00, sampled from the selected tab in game. Use it only as a fill, with ink-colored text on top; in the light theme never use it for lines or text. The same applies to hover: only the primary button wipes in the accent on hover. Links, pill buttons and list rows just lighten or get a thicker underline.
  2. Selection depends on direction:
    • Vertical lists: hover lightens the row; the selected row turns dark with light text, and an accent bar drops in on the left.
    • Horizontal tabs: the selected tab fills solid with the accent. On switch, the old block collapses and the new one opens sideways from its center.
  3. Button shape shows priority: the primary action is a block with its bottom-right corner cut; secondary actions are pills with a round icon at the right end. At most one primary action per button group.
  4. Put a path at the top left of every page: // Work / About me. Levels you can go back to are links.
  5. Numbers are decoration, and they must be true: set IDs, dates and current / total counters in wide tabular figures. Never invent data or add fake technical text. The same holds for copy: describe a product (features, supported scope, installation) only from what the user gave or the project's own docs, and keep their scope. Where there is no source, write a placeholder such as [TODO: ...] instead of filling it in.
  6. Show key caps for shortcuts: for example ← → next to page buttons. Show them only on devices with a fine pointer.
  7. Background: closed contour lines: one patch in each of two corners, 6% to 9% opacity, every fifth line heavier, not animated.
  8. Short, firm motion: hover 90 ms, selection 110 to 120 ms, curve cubic-bezier(.2,0,0,1). Turn everything off when the system asks to reduce motion.

Pick a page type first

Decide which kind of page you are building before you start. All three share the same colors and components; they differ in how bold they get. When unsure, choose Reading.

TypeUsed forHowIn-game equivalent
ReadingArticles, project details, settings, helpOne text column, about 65 Latin or 38 CJK characters wide; accent only on the current nav item and the primary button; contours optionalEncyclopedia, archives
ShowcaseHome pages, portfolios, landing pagesLarge wide headings, outline type allowed; large numbers as background; contours on; content may fade in block by blockMain menu, shop
WorkbenchAdmin pages, dashboards, tools, extension settingsVertical list nav on the left, tabs on top; mostly tables, numbers and forms; no large headings; motion only in response to actionsInventory, equipment, friend list

Components

All live in assets/terrain.css with the tu- prefix. examples/demo.html shows each one.

ComponentClassesNotes
Path titletu-crumbRule 4
Vertical listtu-listMark the current item with aria-current
Horizontal tabstu-tabs tu-tabMark the current tab with aria-selected="true" or aria-current
Primary / secondary buttontu-btn / tu-btn--pill + tu-btn__iconRule 3
Key hinttu-kbdRule 6
Field rowtu-fields tu-sepSeparate metadata with a vertical bar │
Paneltu-panelA flat block: no radius, shadow or border
Tabletu-table-wrap tu-tableSmall wide header labels; right-align numeric columns with tu-right; scrolls sideways on narrow screens
Inputtu-field tu-input tu-hintOn focus the underline thickens and an accent bar appears on the left
Errortu-error, plus aria-invalid="true" on the inputA small accent square and one sentence on how to fix it; no red text
Switchtu-switch"On" is a current state, so the track fills with the accent
Dialog<dialog class="tu-dialog">Buttons sit in a footer bar: one primary, cancel as a pill; it sharpens in from a blur
Toasttu-toastA dark bar with an accent bar on the left; slides in from the left and leaves after 2 seconds
Empty statetu-emptyA dashed box with one sentence on what will appear here, optionally one primary button
Loadingtu-progress, plus tu-progress--busy while waitingA 2 px line; when progress is known, set --tu-value and show the percentage

No red. Warnings, failures and pending states use the small accent square with ink text. Put irreversible actions such as delete behind a confirmation dialog.

For anything not in this table, derive it from the eight rules: whether it is "current" or "primary" decides if it may use the accent; whether it is primary or secondary decides block or pill; whether it can be clicked decides if it lightens on hover.

Motion

ActionDurationHow
Hover lighten90 msBackground color transition
List selection bar drops in110 msscaleY(0 → 1)
Tab switch120 msAccent block scaleX(0 → 1), opening from the center
Primary button hover280 msAccent wipes in from the left
Page changeOut 320 ms, in 480 msOld page blurs and fades out; new page fades in block by block, 100 ms apart

Don't

  • Unseen markers (red dots, NEW badges): in the game they push players to collect rewards; on a portfolio or ordinary site they feel like nagging.
  • Frosted glass, glitch tearing, scan lines, glow, large accent fills, rounded cards with shadows.
  • Game-only elements such as 3D carousel menus, character art and rarity color bars.
  • Any official game assets: screenshots, logos, icons, character art, copy, or the official font files.

Type

  • Latin text and numbers: Saira (open source, SIL OFL). Labels stretched to 125%, all caps, 0.06em tracking. The official site adds no tracking to its wide labels; a little is kept here for small sizes.
  • Chinese: Noto Sans SC or the system sans. No serif or brush faces for body text.
  • All numbers tabular (font-variant-numeric: tabular-nums).

Delivering a single HTML file

  • Use the terrain.css classes as they are; do not add page-level overrides that change their colors. If a change is needed, the component has a problem and should be reported back to the skill.
  • Put terrain.css in a <style> element and contours.js in a <script> element. Before inlining any script, make sure it contains no literal </script>; if it does, write it as <\/script>.
  • If the page must work offline, embed Saira as a woff2 data URI in @font-face; otherwise link Google Fonts and keep the fallback fonts.

Checklist before delivery

  • A page type was chosen, and heading sizes from different types are not mixed on one page.
  • The accent appears only on the current location and primary actions; there is no red on the page.
  • Each button group has at most one block primary button; the rest are pills.
  • Vertical lists and horizontal tabs use their own selection styles.
  • Every page has a // path title.
  • All numbers are real data; every product statement has a source and does not overstate its scope.
  • Both light and dark themes were checked; nothing scrolls sideways at phone width (about 400 px).
  • Keyboard focus is visible; everything is still with reduced motion on.
  • No official game assets are used.

Files

FileContents
assets/terrain.cssColor tokens (light and dark) and all components
assets/contours.jsContour background, one line to set up: TerrainContours.mount(canvas)
examples/demo.htmlEvery component on one page, ready to open
examples/screenshots/The component page in light, dark, phone width, and the dialog
references/research.mdResearch notes: what was observed, what was kept, what was left out

Related Skills