Interactive terminal-style portfolio website for Alexandre Gossard (@hakkaofdev).
Live: https://hakkaofdev.fr
- Terminal UI with command input, command history, and autocomplete
- Built-in commands:
help,projects,experiences,skills,about,education,contact,cv,repo,theme,stats,echo,clear,reset,spotify - Optional Spotify integration:
- Header "Now Playing" widget (polls every 15s)
- Terminal commands:
spotify now,spotify top,spotify history
- Theme command with modes:
theme dark,theme light,theme system - Dynamic CV PDF endpoint with preview/download:
/api/cv,/api/cv?download=1 - Light/dark theme toggle (
next-themes) - Animations (
motion) - SEO-friendly metadata +
sitemap.xmlandrobots.txt - Dynamic social preview image (
/opengraph-image) + JSON-LD person schema - Vercel Speed Insights
- Next.js (App Router) + React
- TypeScript
- Tailwind CSS v4 (CSS-first config) +
tailwindcss-animate - TanStack Query (
@tanstack/react-query) - Spotify Web API (refresh-token flow)
- Node.js (recommended: 22+, see
.node-version) - pnpm (repo is pinned to
pnpm@9.14.2)
pnpm installpnpm devThen open http://localhost:3000
pnpm build
pnpm startpnpm lint
pnpm typecheck
pnpm audit
pnpm formatCreate a .env.local file at the repo root (you can start from .env.example):
# Used by app/sitemap.ts and app/robots.ts
NEXT_PUBLIC_SITE_URL=http://localhost:3000
# Optional (enables Spotify commands + header widget)
SPOTIFY_CLIENT_ID=
SPOTIFY_CLIENT_SECRET=
SPOTIFY_REFRESH_TOKEN=Notes:
NEXT_PUBLIC_SITE_URLis used to build absolute URLs inapp/sitemap.tsandapp/robots.ts.- Spotify variables are read in
app/actions.ts:- Access token is obtained via the Spotify token endpoint using the refresh token.
- Data is fetched from
currently-playing,top/tracks, andrecently-played.
- Required Spotify scopes typically include:
user-read-currently-playing(oruser-read-playback-state)user-top-readuser-read-recently-played
If you do not set Spotify env vars, Spotify UI will stay hidden and the spotify ... commands will return "No data found.".
Top-level commands are defined in components/commands/command-descriptors.ts and rendered via components/commands/registry.tsx.
Spotify subcommands are described in components/commands/command-descriptors.ts and wired in components/commands/spotify-registry.tsx.
| Command | What it does |
|---|---|
help |
List all available commands |
projects |
Show projects grid (opens links in a new tab) |
skills |
Show categorized skills |
about |
Show personal details (languages/hobbies/etc) |
education |
Show education timeline |
contact |
Show primary contact methods and social profiles |
cv |
Open CV preview/download actions (powered by /api/cv) |
repo |
Show repository details and clone command |
theme |
Show current theme and available theme modes |
theme dark |
Switch to dark mode |
theme light |
Switch to light mode |
theme system |
Follow operating system theme |
stats |
Show coding and GitHub activity stats |
echo <message> |
Print custom text in the terminal |
experiences |
Show experience timeline |
clear |
Clear terminal history |
reset |
Reset terminal to the initial welcome state |
spotify |
Show Spotify sub-command help |
spotify now |
Show currently playing track |
spotify top |
Show top tracks |
spotify history |
Show recently played tracks |
Most portfolio content lives in lib/constants.ts:
- Social links (
SOCIALS) - Projects list (
PROJECTS) - Skills (
SKILLS) - Education (
EDUCATION) - Experiences (
EXPERIENCES)
To add a new terminal command:
- Add the command + description to
COMMANDSincomponents/commands/command-descriptors.ts(autocomplete/help + did-you-mean). - Create a renderer component in
components/commands/renders/. - Wire it in
components/commands/registry.tsx(COMMAND_RENDERERSmap).
To add a new Spotify sub-command:
- Add the sub-command + description to
SPOTIFY_COMMANDSincomponents/commands/command-descriptors.ts. - Add the renderer in
components/commands/renders/spotify/. - Wire it in
components/commands/spotify-registry.tsx.
To add or modify theme modes:
- Update
THEME_COMMANDSincomponents/commands/command-descriptors.ts. - Keep parser/validation aligned in
components/commands/renders/CTheme.tsx.
To customize the CV PDF:
- Update data mapping/truncation in
lib/cv/cv-pdf.data.ts. - Update typography/layout in
lib/cv/cv-pdf.styles.ts. - Update rendering blocks in
components/cv-pdf/CVSections.tsx. - API endpoint is
app/api/cv/route.tsx(/api/cv,/api/cv?download=1).
This repo is designed to deploy cleanly to Vercel (Speed Insights is already integrated).
Set these environment variables in your hosting provider:
NEXT_PUBLIC_SITE_URL(e.g.https://hakkaofdev.fr)- Spotify variables if you want Spotify features
GitHub Actions workflows are included:
.github/workflows/ci.yml: runspnpm lint,pnpm typecheck, andpnpm buildon PRs/pushes tomain.github/workflows/dependency-audit.yml: runspnpm audit --prod --audit-level=highon PRs + weekly schedule
- Spotify album art comes from
https://i.scdn.coand is allowlisted vianext.config.ts(images.remotePatterns).
No license file is currently included in this repository.