registry
@automindzsheets 01–77shadcn 4.x
SHEET 46

Terminal

block / motion / marketing

The staged CLI session every dev-tool homepage ships — commands typing themselves out with their output landing under them — with the whole schedule derived from the config and no client boundary.

type
block
files
3
registry deps
skeleton
npm deps
none

installs

  • lib/automindz/terminal-lines.ts
  • components/automindz/terminal.tsx
  • styles/automindz-terminal.css
  • Every line's start is derived from the lines before it — no hand-authored delays
  • Runs once and never replays: the finished session is where it spends its life
  • One <pre> of real text — selectable, copyable, findable, and the $ prompts excluded
  • Typing is a stepped clip-path, and in a monospace face a step is exactly one glyph
  • Import styles/automindz-terminal.css once in your layout

Edit lib/automindz/terminal-lines.ts, not the component, and pass it — lines has no default here (<Terminal lines={TERMINAL_SESSION} />). The stylesheet is not optional: add import "@/styles/automindz-terminal.css" to your root layout once, or nothing types. Skipping it is safe and never blank — the whole session is on screen instantly, complete, in the right order and the right ink, which is also the prefers-reduced-motion, headless and print path, and where the session spends almost all of its life anyway because **it runs once and never replays** (bump a key if you genuinely want another pass). Every line's start is derived from the lines before it, so inserting a line in the middle pushes the rest by exactly that line's cost and retimes nothing by hand; delay on a line buys a real pause and is clamped to 2.4s, and a command types at a capped rate so a 400-character docker run cannot run away with the session. Only a command types — everything else is a machine printing, and a machine does not type. chrome is **off by default**, because the frame around a terminal is almost always your own Card and two nested frames read as a mistake; title is only rendered when chrome is on, and the three dots are aria-hidden decoration rather than buttons that do nothing. Pass label to name the transcript: it is a focusable <pre> that scrolls sideways rather than wrapping. Pass lines while loading too — the config is where the skeleton's height comes from, so nothing jumps when the real session lands. An empty lines renders nothing at all rather than an empty frame. Dials: --automindz-terminal-fade, --automindz-terminal-caret-width, --automindz-terminal-caret-blink (floored at 0.8s in the stylesheet, so it can only be made slower).

Variations

one state per section

01

The default: install, fail, repair, land green

Watch the schedule rather than the typing: every line starts at the previous line's end plus a beat, so inserting a line into the middle of the config pushes the six after it by exactly that line's cost and retimes nothing else. The failure and the repair are the point — a marketing terminal that only ever prints success is a screenshot with no data in it. Nothing is a live region, so a screen reader is not read the session as it plays.

fluid
Install, migrate, and run the suite
npm install
added 214 packages in 3.8s
npm run db:migrate
Applying 2 pending migrations
✗ 0031_add_sessions failed: relation "sessions" already exists
npm run db:migrate -- --resolve 0031
Marked 0031 as applied, ran 0032
✓ Schema is up to date — 32 migrations, 0 pending
02

With the window frame, standing alone

chrome is off by default because the frame is almost always the caller's Card; turn it on for a terminal with nothing around it, and title is only rendered here. The three dots are aria-hidden decoration and deliberately not buttons — three window controls that do nothing are a keyboard trap dressed as an affordance.

fluid
~/apps/console — zsh
Install, migrate, and run the suite
npm install
added 214 packages in 3.8s
npm run db:migrate
Applying 2 pending migrations
✗ 0031_add_sessions failed: relation "sessions" already exists
npm run db:migrate -- --resolve 0031
Marked 0031 as applied, ran 0032
✓ Schema is up to date — 32 migrations, 0 pending
03

A session with no commands in it, and one real pause

Only the first line types; everything under it is a machine printing, and a machine does not type — it appears whole after its beat. The upload carries delay: 1.6, which is the one dial worth reaching for and is clamped at 2.4s, so a mistyped delay: 600 cannot park the session for ten minutes.

fluid
Deploying to production
npm run deploy -- --env production
Building… 42 routes, 1.2MB gzipped
Uploading to edge (18 regions)
Warming caches
✓ Live at 14:02:11 — 0 failed health checks
04

A line too long for the box

The docker line is 171 characters and still types in 1.6s, because the per-character rate is capped: runtime is a function of how many lines there are, never of how much text somebody pasted into one of them. It does not wrap — the transcript scrolls sideways, and the pre is focusable with a visible ring so reaching the end of it is a keyboard operation and not a mouse-only one.

fluid
One line nobody should have to read
docker run --rm -it --name registry-preview -p 3000:3000 -e NODE_ENV=production -e NEXT_TELEMETRY_DISABLED=1 -v $(pwd)/.next:/app/.next ghcr.io/automindz/components:latest
Unable to find image locally, pulling…
✗ denied: requested access to the resource is denied
docker login ghcr.io
✓ Login succeeded
05

Loading, at the transcript's real height

The skeleton rows are the shape of the session they stand in for — one per line, at the transcript's own line height, each as wide as that line's real character count in ch, which is exact because the face is monospace. Pass lines while loading: the config is where the height comes from, so nothing under the block moves when the session lands.

fluid
06

No lines at all

An empty config renders nothing — not an empty frame, which at the size of a terminal reads as a failed load. The dashed box below is the preview's, and it is empty on purpose.

fluid
07

Finished is the base state

Turn on Reduce Motion in your OS and reload: the whole session is on screen instantly, complete, in the right order and the right ink, with no caret parked anywhere. That is the same picture an install renders with the stylesheet import forgotten, and the same one a headless render and a print stylesheet get — and it is where the session spends almost all of its life anyway, because it runs once and does not replay. Select it and paste it: the $ and # prompts are excluded, the ✓ and ✗ are not, because those are the line's own content.

fluid
Install, migrate, and run the suite
npm install
added 214 packages in 3.8s
npm run db:migrate
Applying 2 pending migrations
✗ 0031_add_sessions failed: relation "sessions" already exists
npm run db:migrate -- --resolve 0031
Marked 0031 as applied, ran 0032
✓ Schema is up to date — 32 migrations, 0 pending