A terminal-style personal homepage for Martin Zachariassen β back-end developer with 9 years of experience in architecture, integrations and production services. Instead of a traditional portfolio layout, everything is navigated through typed commands: about, experience, skills, links, and more.
Built with React, TypeScript and Vite. Styled with a Tokyo Night colour palette. No CSS framework β just design tokens and plain CSS.
# Install dependencies
npm install
# Start dev server
npm run dev
# Type-check
npm run typecheck
# Production build
npm run buildType help in the terminal to see all available commands. Type help --secret for more.
| Command | Description |
|---|---|
help |
Show available commands |
about |
Who I am |
skills |
Areas of focus & interests |
experience |
Work history |
contact |
How to reach me |
links |
GitHub, LinkedIn, homepage |
open <target> |
Open a link - github Β· linkedin Β· homepage |
whoami |
Who is this? |
ls / ls -la |
List "files" |
pwd |
Print working directory |
clear |
Clear the screen |
matrix |
π |
src/
βββ App.tsx
βββ main.tsx
βββ vite-env.d.ts
βββ components/
β βββ NameHeader/
β β βββ NameHeader.tsx # Name + tagline header shown above the terminal
β β βββ NameHeader.css
β βββ Terminal/
β βββ Terminal.tsx # Main terminal component
β βββ Terminal.css
β βββ components/
β β βββ OutputLine.tsx # Renders a single output line
β β βββ OutputLine.css
β β βββ TerminalPrompt.tsx # Input prompt component
β βββ hooks/
β β βββ useBanner.ts # Boot banner logic
β β βββ useCommandRunner.ts # Command dispatch
β β βββ useEasterEggs.ts # Easter egg triggers
β β βββ useResize.ts # Drag-to-resize (desktop only)
β β βββ useViewport.ts # Viewport size tracking
β β βββ useViewportEvents.ts
β βββ state/
β βββ terminalReducer.ts # Terminal state management
βββ easter/
β βββ MatrixOverlay.tsx # Matrix rain canvas effect
β βββ MatrixOverlay.css
β βββ useKonami.ts # Konami code listener
βββ styles/
β βββ global.css # Design tokens, reset, global styles
βββ terminal/
βββ parseCommand.ts # Input parser
βββ text.ts # Linkify utility
βββ commands/
βββ index.ts # Command registry
βββ types.ts # Shared command types
βββ about.ts
βββ contact.ts
βββ easter.ts
βββ experience.ts
βββ focus.ts
βββ help.ts
βββ system.ts
βββ tech/
βββ index.ts
βββ backend.ts
βββ build.ts
βββ data.ts
βββ ops.ts
βββ platform.ts
βββ testing.ts
public/
βββ favicon.ico / favicon*.png # All favicon sizes
βββ apple-touch-icon.png
βββ icon-192.png / icon-512.png
βββ site.webmanifest # PWA manifest
βββ robots.txt
βββ sitemap.xml
βββ .nojekyll # Prevents Jekyll processing on GitHub Pages
scripts/
βββ generate-favicons.mjs # Generates all favicon sizes from favicon.png
| Area | Technology |
|---|---|
| Framework | React 19 |
| Language | TypeScript 5 |
| Build tool | Vite 7 |
| Styling | Plain CSS with design tokens - no framework |
| Font | JetBrains Mono via Google Fonts |
| Hosting | GitHub Pages |
| Analytics | Umami - cookieless, GDPR-compliant, self-hosted |
Deployments are triggered by publishing a GitHub Release. The workflow automatically:
- Checks out
main - Sets
VITE_APP_VERSIONfrom the release tag (shown in the boot sequence) - Fetches the latest Umami analytics script
- Builds with Vite (Terser, vendor chunk splitting,
es2022target) - Deploys to GitHub Pages via
actions/deploy-pages
To release a new version:
# 1. Merge your work to main
# 2. Go to GitHub β Releases β Draft a new release
# 3. Create a new tag (e.g. v1.2.0), target main, publish
# β Deployment starts automaticallyManual deploys are also available under Actions β Deploy to GitHub Pages β Run workflow.
| Script | Description |
|---|---|
npm run dev |
Start local dev server |
npm run build |
Type-check + production build |
npm run typecheck |
Run TypeScript compiler check only |
npm run preview |
Preview the production build locally |
npm run generate-favicons |
Regenerate all favicon sizes from public/favicon.png |
- WCAG AA colour contrast throughout
- Skip-to-content link for keyboard users
role="log"+aria-live="polite"on terminal output- All interactive elements have descriptive
aria-label :focus-visiblestyles for keyboard navigation- Non-blocking font loading (
media="print"swap trick) - Vendor chunk splitting for better cache utilisation
- Self-hosted Umami script β no third-party DNS lookup
color-scheme: darkto prevent flash of white on loadcontain: layout painton terminal for paint isolation
Modern browsers only - Chrome, Firefox, Safari, Edge (last 2 versions).
No IE11, no legacy polyfills. Build target: es2022.
This is a personal site - PRs are not expected.
Feel free to fork it and use it as inspiration for your own terminal portfolio.
MIT Β© 2026 Martin Zachariassen