No.247 · Navigation· New
Portfolio Terminal
A portfolio you browse from a prompt, where the output is the navigation. Every project, folder and command it prints is a live token: click one and the command types itself and runs, so the scrollback becomes the path you took — and visitors who have never used a shell learn it by clicking.
The prompt
Written for the variant you picked above: Night
Build a portfolio that is browsed through a terminal, where everything the terminal prints is also navigation. Frame: a 60rem-wide panel (10px radius, a 1px hairline ring), 46rem tall at most, set entirely in a monospace (JetBrains Mono 14/22, ligatures off). No window dots or OS chrome: a 38px title strip reads 'Noor Haddad — index' (the second word is the current place, in the accent) on the left and key hints on the right ('tab complete · ↑ history · ctrl l clear' as small outlined keys). Below it the scrollback, then the live prompt, then a suggestion rail. Every command in the scrollback starts with a faint two-digit sequence number in a 4ch gutter ('03'), then the prompt 'noor@studio ~/work ›' (host muted, path in the accent, a bold '›'), then the command in semibold. Output lines indent to the gutter. The idea: any noun in the output — a project name, a folder, a suggested command — is a button styled as text with a dotted underline (project names in the accent and semibold). Clicking one types the command into the prompt a character at a time (22ms each) and runs it, so the visitor sees the command they could have typed. Output reveals a line at a time (16ms per line). The view stays pinned to the bottom unless the reader has scrolled up. Commands: whoami (name, role and city, two short paragraphs, 'now' line, three starting tokens); ls (work/ and four .txt files as tokens; 'cat about.txt' runs whoami); ls work or cd work + ls (numbered project rows: '01 Tidewater 2025 tide tables for small harbours'); open <slug|number> prints a case file — a dashed-rule header '01 / 04 Tidewater 2025', then an ASCII plate generated deterministically from the project's name (58×9 characters from the ramp ' .:-=+*#%', one of three fields — swell, rings or strata — with faded edges, in the accent, rows wiping in 35ms apart), then aligned 'what / role / stack' rows, a paragraph, an 'outcome' line in green, and '← prev next → all work' tokens; experience (a vertical timeline drawn with ● ○ │); skills (bars of █ and ▌ on a dotted track); contact (email with a small 'copy' button that becomes 'copied ✓'); history (each entry runnable); help (every command as a token with a one-line description); clear. Friendly aliases work (about, work, projects, cv, email, hire). Unknown input answers 'not found: wrk — did you mean work? · help' with the suggestion clickable (edit distance). cd into a project explains it is a project and offers open. The live prompt: a real input, transparent, under a rendered copy of the text with a block caret (solid while focused, blinking after 0.6s idle, an outline when unfocused) and grey ghost text for the first completion. Tab completes and cycles (commands, project slugs, folders, files), → accepts the ghost, ↑/↓ walk history, Enter runs, Escape clears, Ctrl+C cancels the line with '^C', Ctrl+L clears the screen. Suggestion rail (bottom, 52px, slightly raised background): a small 'TRY' label and 3–5 keycap buttons (6px radius, a 2px darker bottom edge that presses down) chosen from context — after whoami: ls work, experience, skills, contact, help; after opening a project: the next project, ls work, contact, cd ~. On load the terminal types and runs whoami itself. Selected variant — Night (night): Palette for this theme (Night): --ptrm-accent #e2a65b; --ptrm-bar #1b1a17; --ptrm-bg #141311; --ptrm-dim #8f8879; --ptrm-err #e98a6c; --ptrm-faint #4a463e; --ptrm-focus #e2a65b; --ptrm-ink #e8e2d4; --ptrm-key #201e1b; --ptrm-key-edge rgb(0 0 0 / 0.55); --ptrm-line rgb(232 226 212 / 0.09); --ptrm-ok #a9c48a; --ptrm-tok-bg rgb(226 166 91 / 0.14). Treat these as the root colour tokens, one value per role, and name them to suit your code. Select it with the theme option set to "night". Keep every dimension, spacing value, state and motion from the brief unchanged, and keep text at 4.5:1 contrast or better on these surfaces. This selection takes precedence over references to other themes or options in the general brief. Implement this selected appearance; do not add a variant picker or alternative appearances unless requested. Implementation requirements: Use React and TypeScript. Keep the component self-contained, with uniquely scoped CSS and no animation libraries. Include required imports, styles and font setup in the result. Interaction: Type commands and press Enter, or click anything underlined in the output and the command types itself and runs. Tab completes (again to cycle), → accepts the grey suggestion, ↑/↓ recall history, Escape clears the line, Ctrl+C cancels it, Ctrl+L clears the screen. The rail under the prompt offers the likely next commands. Motion: Clicked commands type themselves at 22ms a character; output appears a line at a time; project plates wipe in row by row; the caret blinks only when idle; keycaps press down 2px. Reduced motion runs commands instantly and keeps the caret still. Accessibility: The scrollback is a polite log; each command's output is a labelled section; the prompt is a labelled text input; every token is a real button whose name says which command it runs; plates are images with a text label; the rail is a labelled navigation of buttons. Nothing depends on the visual caret. Responsive behavior: Below 620px of its own width the host name and key hints drop, gutters tighten and the plate scales its type to fit. On touch screens the rail becomes the main control — 40px keycaps in a scrolling row — tapping the output never raises the keyboard, only tapping the prompt does. Touch: The suggestion rail and every underlined token are tap targets, so the whole portfolio can be browsed without the keyboard. Preserve keyboard access, visible focus and reduced-motion behavior. Keep fictional demo data and simulated service calls in a separate usage example; expose callbacks for real actions and recover from rejected requests. Keep usage-example links inside the demo: use local buttons or prevent navigation. Demonstration links must not navigate to Vitrine routes or open other pages; preserve real URL support in the reusable component itself. Verify the result at narrow and wide viewport sizes, with keyboard input and reduced motion enabled.
Notes
- Interaction
- Type commands and press Enter, or click anything underlined in the output and the command types itself and runs. Tab completes (again to cycle), → accepts the grey suggestion, ↑/↓ recall history, Escape clears the line, Ctrl+C cancels it, Ctrl+L clears the screen. The rail under the prompt offers the likely next commands.
- Motion
- Clicked commands type themselves at 22ms a character; output appears a line at a time; project plates wipe in row by row; the caret blinks only when idle; keycaps press down 2px. Reduced motion runs commands instantly and keeps the caret still.
- Accessibility
- The scrollback is a polite log; each command's output is a labelled section; the prompt is a labelled text input; every token is a real button whose name says which command it runs; plates are images with a text label; the rail is a labelled navigation of buttons. Nothing depends on the visual caret.
- Responsive
- Below 620px of its own width the host name and key hints drop, gutters tighten and the plate scales its type to fit. On touch screens the rail becomes the main control — 40px keycaps in a scrolling row — tapping the output never raises the keyboard, only tapping the prompt does.
- On touch
- The suggestion rail and every underlined token are tap targets, so the whole portfolio can be browsed without the keyboard.