2026-01-30 — 5 min read
Building a Modern Portfolio with React Router v7 and Tailwind 4
Introduction
Building a portfolio website is a rite of passage for many developers. It's a chance to showcase your skills, experiment with new technologies, and create something that represents you professionally. In this post, I'll share my experience building this portfolio using React Router v7 and Tailwind CSS v4.
Why React Router v7?
React Router v7 brings some exciting changes to the table:
- File-based routing - Routes are automatically generated based on your file structure
- Built-in data loading - The
loaderfunction makes data fetching seamless - Type safety - Better TypeScript integration with
useLoaderData - Server-side rendering - Out of the box SSR support
Here's an example of how I set up a route with data loading:
export async function loader({ params }: LoaderFunctionArgs) {
const project = getProjectBySlug(params.slug);
if (!project) {
throw new Response('Not found', { status: 404 });
}
return { project };
}
Tailwind CSS 4: What's New?
Tailwind CSS v4 introduced several improvements:
1. CSS-first Configuration
Instead of JavaScript configuration, Tailwind 4 uses CSS for theming:
@theme {
--font-sans: "Inter", "system-ui", "sans-serif";
--color-primary: #3B82F6;
}
2. Dynamic Theming
I implemented a theme system that allows users to switch between Brown and Pink themes:
[data-theme="brown"] {
--bg-primary: #dedbca;
--bg-secondary: #6E5034;
--text-primary: #000;
}
[data-theme="pink"] {
--bg-primary: oklch(93.6% 0.032 17.717);
--bg-secondary: #ffa1a3;
--text-primary: #000;
}
Key Features
Dynamic Theme Switching
Users can choose between Brown and Pink themes, with their preference saved to localStorage:
const setTheme = (newTheme: Theme) => {
setThemeState(newTheme);
localStorage.setItem('theme', newTheme);
};
Markdown Blog System
The blog system uses gray-matter for frontmatter parsing and marked for Markdown rendering with syntax highlighting powered by highlight.js.
Responsive Design
Every component is designed mobile-first, ensuring a great experience on all devices.
Lessons Learned
- Start with theming - Setting up CSS variables early makes styling consistent
- Use semantic HTML - It improves accessibility and SEO
- Keep components small - Easier to maintain and test
What's Next?
I'm planning to add:
- Dark mode support
- Blog search functionality
- Project filtering by technology
Thanks for reading! Feel free to explore the portfolio and reach out if you have any questions.