A clean, minimal portfolio website built with Next.js 15 and intended for server-capable deployment on Vercel.
- ✨ Built with Next.js 15 and App Router
- 🎨 Styled with Tailwind CSS
- 📱 Fully responsive design
- ☁️ Realtime Spotify now-playing via a server route
- 🔧 shadcn/ui components
# Install dependencies
npm install
# Run development server
npm run dev
# Build for production
npm run build
# Run a production build
npm run buildThe homepage includes a Spotify-powered now-playing avatar backed by a live Next.js route handler at /api/now-playing.
Required environment variables:
SPOTIFY_CLIENT_IDSPOTIFY_CLIENT_SECRETSPOTIFY_REFRESH_TOKEN
How it works:
- the frontend polls
/api/now-playing - the route handler refreshes a Spotify access token with the stored refresh token
- the server calls Spotify's
currently-playingAPI - the response is sanitized before it reaches the client
This gives you near-realtime updates without a cron snapshot branch.
To fetch a refresh token locally:
- Add
SPOTIFY_CLIENT_IDandSPOTIFY_CLIENT_SECRETto.env.local - Add the same redirect URI to your Spotify app settings
- Run:
npm run spotify:authBy default the auth helper uses http://127.0.0.1:3124/callback. Override it with SPOTIFY_REDIRECT_URI if needed.
- Import the repository into Vercel.
- Add
SPOTIFY_CLIENT_ID,SPOTIFY_CLIENT_SECRET, andSPOTIFY_REFRESH_TOKENto the project environment variables. - Use the default Next.js build settings.
- Redeploy after adding the environment variables.
Notes:
- This app is no longer configured as a static export because
/api/now-playingrequires a server runtime. - Vercel Hobby is sufficient for a personal site with lightweight polling.
├── app/ # Next.js App Router pages
│ ├── about/
│ ├── podcasts/
│ ├── talks/
│ ├── writing/
│ └── page.tsx # Home page
├── components/ # Reusable UI components
├── public/ # Static assets
├── .github/workflows/ # GitHub Actions
└── next.config.mjs # Next.js configuration
MIT License - feel free to use this as a template for your own portfolio!