尚未检测到更新。GitHub 发布版本后会显示在这里。
Website for copperhead, the open source AI agent for PCB design. Live at copperhead.chouhan.ai
翻译准备中
正在加载完整 README。
查看完整 README ↗Website for Copperhead, the open source AI agent for PCB design. Live at copperhead.sh.
Single static page. Astro, vanilla CSS, no client framework, no CMS, no backend. Built to website-spec.md; copy is verbatim from website-content.md.
npm install
npm run dev # http://localhost:4321
npm run build # -> dist/
npm run shots # screenshot + layout audit against the running dev server
The page gates on these at build time, so nothing renders broken while they are
missing. Drop the file into public/ and it appears on the next build.
| File | Effect when added |
|---|---|
copperhead-demo.mp4 | the #demo section appears |
demo-poster.png | poster frame on the video |
copperhead-demo.vtt | captions track (narration script is in pitch-script.md) |
open-telegraph.webp | replaces the placeholder panel in the proof card |
og.png | currently a generated wordmark card; replace with the 1200x630 board render |
The hero is built to be exactly one viewport tall, and the rules that keep it that way are spread across two components, so they are worth stating in one place before anyone edits either.
.hero is min-height: 100svh — a floor, not a fixed height. On any screen
with the room it is exactly the fold; on one without, it grows and the page
scrolls. It is deliberately not height, because a fixed height plus
overflow: hidden silently shears off whatever sits at the bottom, and what
sits at the bottom is the live-stats row.
Order of sacrifice, when the stack does not fit: the terminal keeps its full
height and the stats row goes below the fold. The transcript is the product
and has to be legible; the stats read just as well one scroll down. Nothing in
the hero column shrinks — .hero .wrap > * { flex: none } — so this happens by
the column simply running long.
Three things conspire to make it fit anyway on most screens:
svh term (clamp(18px, 3.4svh, 28px) and
friends), so the rhythm compresses on a short window instead of overflowing.clamp(2.25rem, min(5.6vw, 7svh), 4.5rem). The min() is
the height term: 72px from ~1030px of viewport up, easing to ~50px at 720. It
is the single largest saving in the stack and costs nothing on screens that
have the room.calc(69px + clamp(...)) — clear the fixed navbar, then
leave a gap. The bar's 69px is a constant the hero cannot otherwise see, and a
padding expressed as a bare svh fraction shrinks toward it on a short
viewport until the announcement chip is resting on the rule.justify-content: safe center on the column centres the stack when there is
slack, so a 4K screen distributes it above and below rather than leaving a hole
underneath. safe is load-bearing: it falls back to top-anchored when the
content overflows, which keeps the headline on screen instead of pushing it off
the top.
TerminalDemo.astro has one scale knob: font-size on .term. Width,
chrome height, padding and radius are all stated in em against it, so changing
that number resizes the whole window at a fixed 1.75:1 aspect ratio — 800×458
at the 12px base, 733×420 at 11px, 667×382 at 10px. Do not add px dimensions
to that component; they break the ratio and turn a scaled window into a
letterbox.
This matters more here than in most components. The transcript is
white-space: pre, so its width in characters and its height in rows are both
set by the type size; scaling the two by the same factor is the only way the
window keeps its proportion and keeps the same 72-character lines unwrapped.
The short-desktop steps (min-width: 901px with max-height: 1000px / 760px)
therefore do nothing but restate the base. Two exceptions, both deliberate and
commented in the file: below 900px wide the window is pinned to the column and
cannot hold ratio, so its leading tightens instead; and on phones the bar chrome
opts out of the scale, because at a 9px base the proportional traffic lights
would be 8px and useless to a thumb.
npm run shots drives the running dev server through fourteen viewports and
both themes. It waits for every finite animation to finish before shooting, so
the terminal shows its completed done · verified erc … readout rather than an
empty window.
npm run shots # everything -> shots/ (gitignored)
npm run shots -- --audit # no images, just the table
npm run shots -- --only fhd,2k,4k
npm run shots -- --path /,/pricing
The audit table answers the two questions the layout is built around — does the fold seat the stack, and does the terminal hold 1.75:1 — and flags horizontal overflow and console errors. It covers 1280×720 and 1512×945, the laptop sizes that are easy to forget and exactly where the fold runs out of room.
Needs a Chromium: it finds one from the Playwright cache or a system Chrome, or
set CHROME_PATH. playwright-core is the only devDependency.
Three self-hosted families, subset with pyftsubset to the codepoints the page
actually uses:
| Face | Role |
|---|---|
| Space Grotesk, variable 300-700 | everything set in a sans: headings, body, buttons, UI labels |
| JetBrains Mono 400 / 700 | code, wordmark, section indices, terminal |
| DM Sans 500 (9pt optical) | the nav bar's 15px tier, and nothing else |
Space Grotesk reads as drafting-adjacent next to a mono. It used to hold only the display role, with IBM Plex Sans setting text; Plex has been dropped and the one variable file now does both, since every step of hierarchy the second family provided is available off its own weight axis. That took the page from five font files to four.
以上为 README 的开头部分。其余内容请阅读原文。 查看完整 README ↗