Discover how I built this portfolio website using cutting-edge technologies like Next.js 15, TypeScript, and Tailwind CSS. A deep dive into modern web development practices and design decisions.
When I set out to build this portfolio website, I wanted to create something that would stand out in today's crowded digital landscape. The goal wasn't just to showcase my technical skills, but to demonstrate my approach to problem-solving, attention to detail, and understanding of modern web development principles.
"The best code is the code that never needs to be written." - This philosophy guided every decision in this project.
I chose Next.js 15 for its exceptional developer experience and built-in optimizations. The App Router provides a clean, intuitive way to structure the application, while features like automatic code splitting and server-side rendering ensure lightning-fast loading times.
// Example of a Next.js 15 page component
export default async function BlogPost({ params }: { params: Promise<{ slug: string }> }) {
const { slug } = await params;
const post = await prisma.post.findUnique({ where: { slug } });
// Server-side rendering at its finest
}
TypeScript was a no-brainer for this project. It catches errors at compile time, provides excellent IDE support, and makes the codebase more maintainable. For a portfolio site that demonstrates professional development practices, type safety is essential.
Instead of starting from scratch, I built on Tailwind CSS's utility-first approach. I created a custom design system with CSS custom properties that define colors, spacing, and other design tokens:
:root {
--background: #0b0e11;
--surface: #11161d;
--foreground: #e5e7eb;
--primary: #7c9eff;
--accent: #55d6be;
}
This approach ensures consistency across the entire application while maintaining flexibility.
For the blog functionality, I needed a reliable database. MySQL provides excellent performance and reliability, while Prisma offers a type-safe database client that integrates seamlessly with TypeScript.
The website works beautifully on all devices, from mobile phones to large desktop screens. The layout adapts gracefully, and all interactive elements are touch-friendly.
Key responsive features:
I implemented a theme system that respects user preferences while allowing manual override. The color scheme automatically adjusts based on the user's system settings.
A full-featured blog with:
Secure admin access using NextAuth.js with credential-based authentication. The system includes:
Problem: Creating a consistent theme system that works across all components and respects user preferences.
Solution: Built a CSS custom properties system with fallbacks and proper TypeScript integration:
// Theme-aware component
const ThemeToggle = () => {
const [theme, setTheme] = useState('dark');
// Seamless theme switching
};
Problem: Designing a flexible schema that could handle blog posts, categories, and tags while maintaining performance.
Solution: Used Prisma's schema-first approach to create a clean, normalized database structure:
model Post {
id String @id @default(cuid())
title String
slug String @unique
content String @db.Text
excerpt String?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
Problem: Implementing beautiful markdown rendering that matches the design system.
Solution: Server-side markdown parsing with custom CSS styling:
The initial version was much simpler. I added features incrementally, testing each addition thoroughly before moving on. This approach prevented feature creep and kept the project focused.
The initial setup takes longer, but the benefits in development speed and error prevention are enormous. Type safety caught numerous potential bugs before they could reach production.
Having a consistent design system from the start made the entire development process smoother and the final product more polished. The custom CSS properties made theme changes trivial.
Users expect fast websites. Building performance into the architecture from the beginning is much easier than optimizing later. Next.js 15's built-in optimizations were a game-changer.
Writing this blog post helped me reflect on the development process and identify areas for improvement. Good documentation is as important as good code.
This website is a living project. I plan to:
Building this portfolio website has been an excellent exercise in modern web development. It demonstrates my ability to:
The code is open source and available on GitHub, so feel free to explore the implementation details. If you're interested in working together or have questions about any of the technical decisions, don't hesitate to reach out.
This post was written as part of documenting my development process. I believe in transparency and sharing knowledge, so I'm documenting not just what I built, but how and why I made the decisions I did.
Happy coding! π
Thanks for reading! π