Modern portfolio website built with Next.js 16, React 19, TypeScript, and Tailwind CSS.
This is my third iteration of my personal portfolio website, showcasing my work as a software engineer. Built with cutting-edge technologies and modern web development practices, this project demonstrates my skills in full-stack development, UI/UX design, and software architecture.
Live Site: natee.my.id
- Next.js 16 - React framework with App Router
- React 19 - Latest React with Server Components
- TypeScript - Type-safe development
- Turbopack - Ultra-fast bundler for development
- Tailwind CSS - Utility-first CSS framework
- Shadcn/ui - Re-usable components built with Radix UI
- Magic UI - Beautiful animated components
- Framer Motion - Production-ready animations
- Lucide React - Beautiful icon library
- React Hook Form - Performant form library
- @hookform/resolvers - Validation resolvers
- MDX - Markdown with JSX components
- gray-matter - YAML front matter parser
- next-mdx-remote - Load MDX content
- highlight.js - Syntax highlighting
- Jest - JavaScript testing framework
- React Testing Library - Component testing
- Playwright - End-to-end testing
- ESLint - Code linting
- Vercel Analytics - Web analytics
This project uses Next.js 16 App Router with route groups for logical organization:
src/app/
├── (visitor)/ # Public visitor pages
├── (user)/ # Authenticated user pages
├── (admin)/ # Admin dashboard
├── (authentication)/ # Auth-related pages
├── _components/ # Shared page components
├── actions/ # Server actions
├── api/ # API routes
└── layout.tsx # Root layout
portfolio-v3/
├── src/
│ ├── app/ # Next.js App Router
│ │ ├── (visitor)/ # Public routes (home, blog, projects)
│ │ ├── (user)/ # Protected user routes
│ │ ├── (admin)/ # Admin dashboard routes
│ │ ├── (authentication)/ # Auth routes (login, register)
│ │ ├── _components/ # Page-specific components
│ │ ├── actions/ # Server actions
│ │ └── api/ # API routes
│ │
│ ├── components/ # Reusable components
│ │ ├── ui/ # Shadcn UI components
│ │ ├── magicui/ # Magic UI components
│ │ └── layout/ # Layout components
│ │
│ ├── commons/ # Shared utilities
│ │ ├── constants/ # App constants
│ │ ├── helpers/ # Helper functions
│ │ └── types/ # TypeScript types
│ │
│ ├── services/ # API service layer
│ ├── hooks/ # Custom React hooks
│ ├── lib/ # Library configurations
│ ├── supabase/ # Supabase client
│ └── middleware.ts # Next.js middleware
│
├── __tests__/ # Test files
│ ├── e2e/ # End-to-end tests
│ └── README.md # Testing documentation
│
├── public/ # Static assets
├── content/ # MDX content files
└── misc/ # Miscellaneous files
- Atomic Design: Components organized from atoms to organisms
- Composition over Inheritance: Flexible component composition
- Server & Client Components: Optimized for React Server Components
- React Hooks: useState, useEffect for local state
- Server Actions: Form submissions and mutations
- Theme Provider: Global theme state with next-themes
- Server Components: Data fetched on the server by default
- Supabase Client: Direct database queries
- API Routes: RESTful endpoints for external integrations
- Portfolio Showcase - Projects, skills, and professional experience
- Blog - Technical writing with MDX support for rich content
- Dark Mode - Automatically adapts to your system preferences
- Responsive Design - Works seamlessly on all devices
- Performance - Lightning-fast page loads with Next.js 16
- Smooth Animations - Polished interactions using Framer Motion
- SEO Optimized - Proper meta tags, sitemap, and robots.txt
- Authentication - Secure login with Supabase Auth
- Dashboard - Analytics and content management in one place
- Content Editor - Easy blog post creation and editing
- Visitor Tracking - See who's checking out your portfolio
- LinkedIn Integration - Display your recommendations
- Comprehensive Testing - Unit, component, and end-to-end tests
- Type Safety - Full TypeScript coverage throughout
- Hot Reload - Instant feedback with Turbopack
- Code Quality - ESLint configuration included
- Modern Stack - Built with the latest web technologies
- Node.js 18+ or Bun
- npm, yarn, pnpm, or bun
- Supabase account (for database)
Create a .env file in the root directory:
# Supabase
NEXT_PUBLIC_SUPABASE_URL=your_supabase_url
NEXT_PUBLIC_SUPABASE_ANON_KEY=your_supabase_key
# Domain
DOMAIN=https://your-domain.com
# Email (optional for contact form)
EMAILJS_SERVICE_ID=your_service_id
EMAILJS_TEMPLATE_ID=your_template_id
EMAILJS_PUBLIC_KEY=your_public_key
# Cloudflare Turnstile (optional)
NEXT_PUBLIC_TURNSTILE_SITE_KEY=your_site_key-
Clone the repository
git clone https://github.com/rizkyhaksono/portfolio-v3.git cd portfolio-v3 -
Install dependencies
# Using npm npm install # Using bun (recommended) bun install
-
Set up environment variables
cp .env.example .env # Edit .env with your values -
Run database migrations (if applicable)
# Follow Supabase documentation for migrations -
Start development server
npm run dev # or bun dev -
Open browser
http://localhost:3000
This project includes comprehensive testing using Jest, React Testing Library, and Playwright.
# Run all unit and component tests
npm run test
# Run tests in watch mode (recommended for development)
npm run test:watch
# Run tests with coverage report
npm run test:coverage
# Run end-to-end tests with Playwright
npm run test:e2e
# Run E2E tests with interactive UI
npm run test:e2e:ui
# Debug E2E tests
npm run test:e2e:debug- Unit Tests - Testing utility functions (
src/__tests__/unit/) - Component Tests - Testing React components (
src/__tests__/components/) - Integration Tests - Testing page-level functionality (
src/__tests__/integration/) - E2E Tests - End-to-end browser testing (
__tests__/e2e/)
- ✅ Utility functions (cn helper)
- ✅ UI components (Button, etc.)
- ✅ Layout components
- ✅ Page navigation and routing
- ✅ Theme switching functionality
For detailed testing documentation, see tests/README.md.
Health check endpoint to verify server status.
Response:
{
"timestamp": "2025-12-16T10:30:00Z",
"status": "ok",
"uptime": 3600
}Fetch current Spotify playback information (requires Spotify API setup).
Response:
{
"isPlaying": true,
"title": "Song Name",
"artist": "Artist Name",
"album": "Album Name",
"albumArt": "https://...",
"url": "https://open.spotify.com/track/..."
}Setup Required:
- Spotify app from Developer Dashboard
- Environment variables (runtime on Azure App Service and local
.env):SPOTIFY_CLIENT_IDSPOTIFY_CLIENT_SECRETSPOTIFY_REFRESH_TOKEN(OAuth refresh token with scopesuser-read-currently-playinganduser-read-recently-played)
- Full setup guide: docs/SPOTIFY_SETUP.md
- Helper script:
node scripts/spotify-get-refresh-token.mjs
Fetch weather information (requires weather API setup).
Response:
{
"temperature": 25,
"condition": "Partly Cloudy",
"humidity": 65,
"windSpeed": 12,
"location": "City Name"
}Setup Required:
- Add weather API credentials to environment variables
The service layer is organized by role/context:
Public-facing services:
- ping.ts - Server health check
- spotify.ts - Spotify integration
- weather.ts - Weather data fetching
User-authenticated services for logged-in users.
Admin-only services for dashboard and content management.
The project uses Supabase PostgreSQL. Key tables include:
Example User Table:
CREATE TABLE users (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
email TEXT UNIQUE NOT NULL,
display_name TEXT,
avatar_url TEXT,
created_at TIMESTAMPTZ DEFAULT NOW(),
updated_at TIMESTAMPTZ DEFAULT NOW()
);Example Visitor Tracking Table:
CREATE TABLE page_views (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID REFERENCES users(id),
page_path TEXT NOT NULL,
referrer TEXT,
user_agent TEXT,
created_at TIMESTAMPTZ DEFAULT NOW()
);For your specific schema, check Supabase dashboard or migration files.
- TypeScript: Strict mode enabled - utilize full type safety
- File Naming: Use kebab-case for files (e.g.,
my-component.tsx) - Components: Use PascalCase for component names
- Utilities: Use camelCase for function/variable names
-
Folder Structure:
components/category/ ├── component-name.tsx # Component file ├── component-name.test.tsx # Tests └── index.ts # Named export -
Server vs Client Components:
- Default to Server Components unless you need interactivity
- Use
'use client'directive only when necessary - Minimize client component boundaries
-
Props & Typing:
interface ComponentProps { title: string isActive?: boolean children: React.ReactNode } export function MyComponent({ title, isActive, children }: ComponentProps) { return <div>{children}</div> }
- Use Tailwind CSS utility classes
- Create custom styles in
globals.cssonly when necessary - Leverage Shadcn/ui components for consistency
- Use CSS modules for scoped styles if needed:
styles.module.css - UI layout system: monochrome, square, hairline borders — see
docs/ui/README.mdandsrc/lib/design-system.ts(solid / glass / inset surfaces only)
- Use Zod for schema validation
- Create typed error responses
- Log errors to monitoring service (Sentry, etc.)
Shared instructions for coding agents and the UI design system:
| Resource | Path |
|---|---|
| Canonical agent instructions | AGENTS.md |
| Claude | CLAUDE.md |
| Cursor | .cursorrules + .cursor/rules/ |
| Gemini | .geminirules / GEMINI.md |
| Copilot | .github/copilot-instructions.md |
| UI design system | docs/ui/README.md |
# Kill process on port 3000
# Windows
netstat -ano | findstr :3000
taskkill /PID <PID> /F
# macOS/Linux
lsof -i :3000
kill -9 <PID>- Verify
.envvariables are set correctly - Check Supabase project is active
- Ensure Row Level Security (RLS) policies allow your queries
# Clear build cache
rm -rf .next
npm run build# Clear Jest cache
npm run test -- --clearCache
# Run tests with verbose output
npm run test -- --verbose- Check if Turbopack is running:
next dev --turbopack - Restart dev server
- Clear browser cache
- Use Next.js
Imagecomponent for automatic optimization - Specify
widthandheightprops - Use
priorityprop for above-the-fold images
- Next.js automatically code-splits at route level
- Use dynamic imports for heavy components:
import dynamic from "next/dynamic" const HeavyComponent = dynamic(() => import("./HeavyComponent"))
- Use Supabase indexes for frequently queried columns
- Implement pagination for large result sets
- Consider caching strategies with
revalidateoptions
- Public Variables: Use
NEXT_PUBLIC_prefix only for truly public data - Secret Variables: Keep database credentials, API keys secure
- Never commit
.envfiles
- Use Supabase Auth for user management
- Implement RLS (Row Level Security) policies
- Validate all form inputs with Zod
- Validate request data
- Check user authentication/authorization
- Rate-limit sensitive endpoints using the helper in
commons/helpers/rate-limit.ts
- Automatically enabled in production on Vercel
- Monitor Web Vitals, user interactions
- View dashboard at vercel.com
- Implement tracking in
src/commons/helpers/ - Log important events to database
- Track page views in
api/routes
{
"dev": "next dev --turbopack", // Start development server with Turbopack
"build": "next build", // Build for production
"start": "next start --port 3001", // Start production server
"lint": "next lint", // Run ESLint
"test": "jest", // Run unit tests
"test:watch": "jest --watch", // Run tests in watch mode
"test:coverage": "jest --coverage", // Generate coverage report
"test:e2e": "playwright test", // Run E2E tests
"test:e2e:ui": "playwright test --ui", // Run E2E with UI
"test:e2e:debug": "playwright test --debug" // Debug E2E tests
}- Push your code to GitHub
- Import project on Vercel
- Add environment variables
- Deploy!
This project can be deployed to any platform that supports Next.js:
- Netlify
- Railway
- AWS Amplify
- DigitalOcean App Platform
Contributions are welcome! Please feel free to submit a Pull Request.
- Fork the repository
- Create your feature branch (
git checkout -b feature/AmazingFeature) - Commit your changes (
git commit -m 'Add some AmazingFeature') - Push to the branch (
git push origin feature/AmazingFeature) - Open a Pull Request
This project is licensed under the MIT License - see the LICENSE file for details.
Muhammad Rizky Haksono
- Website: natee.my.id
- GitHub: @rizkyhaksono
- LinkedIn: rizkyhaksono
- Email: mrizkyhaksono@gmail.com
Special thanks to the amazing tools and platforms that made this project possible:
- Next.js - The React framework that powers everything
- Shadcn/ui - Beautiful, accessible components
- Vercel - Seamless deployment and hosting
- Supabase - Powerful backend infrastructure