Skip to content

Repository files navigation

Portfolio

A minimal, terminal-inspired portfolio website built with Next.js 16, React 19, Tailwind CSS 4, and Framer Motion. Features real-time Discord presence via Lanyard, a cryptographic text reveal effect, an interactive 3D tile grid background, and dark/light theme support.


Features

  • Decrypt Text Effect — Characters scramble and reveal themselves letter-by-letter on mount, with interactive click-to-scale micro-animations.
  • 3D Tile Grid Background — A procedurally generated grid that reacts to cursor and touch movement with 3D perspective rotation and proximity-based glow.
  • Real-time Discord Activity — Shows current Spotify playback and gaming activity via Lanyard WebSocket, with "last played" fallback.
  • Dynamic GitHub Projects — Fetches and displays your latest repos with language, stars, forks, and live-link indicators.
  • Hero Slider — Scroll or swipe between intro, contact, collaboration, and activity slides.
  • Dark and Light Themes — Instant toggle with localStorage persistence and flash-free initial load.
  • Custom Cursor — Smooth dot-and-ring cursor with hover and press states on pointer-fine devices.
  • Animated 404 Page — Pixel-art digit grid with auto-redirect countdown.
  • Accessibility — Respects prefers-reduced-motion, keyboard navigation with visible focus rings, and semantic ARIA attributes.

Tech Stack

Layer Technology
Framework Next.js 16 (App Router)
UI Library React 19
Styling Tailwind CSS 4
Animations Framer Motion
Presence Lanyard API (WebSocket + REST)
Language TypeScript

Getting Started

Prerequisites

  • Node.js 18.18 or later
  • npm (comes with Node.js)
  • A Discord account monitored by Lanyard

Installation

# Clone the repository
git clone https://github.com/westopia/portfolio.git
cd portfolio

# Install dependencies
npm install

# Start the development server
npm run dev

The site will be available at http://localhost:3000.

Environment Variables

Create a .env.local file in the project root:

# Required — Your Discord user ID for Lanyard presence
NEXT_PUBLIC_DISCORD_ID=your_discord_user_id

# Optional — Lanyard API key for persisting "last played" data to Lanyard KV.
# If not set, the site falls back to client-side localStorage caching.
LANYARD_API_KEY=your_lanyard_api_key

# Optional — Comma-separated origins allowed during local network dev testing.
# Add your machine's local IP with and without the port so your phone can connect.
# Example: ALLOWED_DEV_ORIGINS=192.168.1.5,192.168.1.5:3000
ALLOWED_DEV_ORIGINS=

How to get your Discord ID: Enable Developer Mode in Discord settings, then right-click your profile and select "Copy User ID".

Lanyard API Key: Only needed if you want the "last played" data to persist server-side across all visitors. You can get it from the Lanyard dashboard after adding the Lanyard bot to your server. Without it, everything still works — it just uses localStorage per browser.

Testing on mobile: To test on your phone over your local network, find your machine's local IP (run ipconfig on Windows or ifconfig on macOS/Linux), then set ALLOWED_DEV_ORIGINS to both the IP and IP with port, separated by a comma (e.g. 192.168.1.5,192.168.1.5:3000). Both are needed because browsers include the port in the origin header. Then open http://<your-ip>:3000 on your phone.


Customization

This portfolio is designed to be forked and personalized. Here is what to change:

Personal Info

Edit app/components/hero-slider.tsx and replace the name, tagline, email, and social links in the slide data.

Edit app/page.tsx and change the GitHub username in getGithubAvatar("westopia").

Edit app/layout.tsx and update metadata.title and metadata.description for SEO.

GitHub Projects

Edit app/components/projects-list.tsx and change the GitHub username in getGithubProjects("westopia"). You can also adjust LANGUAGE_COLORS to add any languages you use.

Discord Presence

Set NEXT_PUBLIC_DISCORD_ID in your .env.local to your own Discord user ID.

Join Lanyard's Discord server so the bot can track your presence.

Theme Colors

Edit app/globals.css and modify CSS custom properties in the :root (dark) and html.theme-light blocks. Key variables: --background, --foreground, --accent, --muted, --dim, --line.

Fonts

Edit app/layout.tsx and replace Geist / Geist_Mono with any Google Font using the next/font module.


Project Structure

app/
├── api/
│   └── activity/
│       └── route.ts            API route — syncs activity to Lanyard KV
├── components/
│   ├── activity-slide.tsx      Spotify and game activity display
│   ├── app-listeners.tsx       Global keyboard and context-menu listeners
│   ├── custom-cursor.tsx       Dot-and-ring cursor with lerp animation
│   ├── decrypt-text.tsx        Scramble-reveal text effect
│   ├── hero-slider.tsx         Main hero section with scroll/swipe slides
│   ├── projects-list.tsx       GitHub repos fetched server-side
│   ├── theme-toggle.tsx        Dark/light mode toggle
│   └── tile-grid.tsx           3D interactive background grid
├── hooks/
│   └── use-lanyard.ts          WebSocket hook for real-time Discord presence
├── types/
│   └── lanyard.ts              TypeScript interfaces for Lanyard data
├── globals.css                 Theme variables, animations, base styles
├── layout.tsx                  Root layout with theme initializer
├── not-found.tsx               Animated 404 page
└── page.tsx                    Home page

Scripts

Command Description
npm run dev Start development server with hot reload
npm run build Create production build
npm run start Serve the production build
npm run lint Run ESLint

Deployment

This project is optimized for Vercel:

  1. Push your repo to GitHub.
  2. Import the repository on vercel.com/new.
  3. Set your environment variables (NEXT_PUBLIC_DISCORD_ID, optionally LANYARD_API_KEY).
  4. Deploy — Vercel auto-detects Next.js.

You can also deploy anywhere that supports Node.js:

npm run build
npm run start

License

This project is open source and available under the MIT License.


Built by Westopia

About

Minimal, terminal-inspired personal portfolio built with Next.js, React, and Tailwind CSS

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages