Building a Portfolio with Tailwind CSS and shadcn/ui
A step-by-step guide to creating a modern portfolio using Tailwind CSS, shadcn/ui components, and dark mode support.
Why Tailwind CSS + shadcn/ui?
Building a portfolio from scratch can be daunting. Tailwind CSS gives you utility-first styling that’s fast to iterate on, while shadcn/ui provides beautifully designed, accessible components you can copy into your project.
The Stack
- Astro — static site generator with island architecture
- Tailwind CSS v4 — utility-first CSS framework
- shadcn/ui — reusable component library
- React — for interactive islands
Setting Up the Project
# Create a new Astro project
bun create astro@latest my-portfolio
# Add Tailwind CSS
bun add tailwindcss @tailwindcss/vite
# Add React integration
bunx astro add react
Dark Mode Implementation
One of the most requested features is dark mode. Here’s how to implement it with a toggle:
function toggleTheme() {
const isDark = document.documentElement.classList.toggle('dark');
localStorage.setItem('theme', isDark ? 'dark' : 'light');
}
The key is persisting the user’s preference in localStorage and applying it before the page renders to avoid flash of unstyled content (FOUC).
Responsive Design Tips
- Mobile-first approach — start with the smallest screen and scale up
- Use container queries — for component-level responsiveness
- Test on real devices — emulators don’t catch everything
Performance Wins
Astro’s island architecture means JavaScript is only loaded where needed. Combined with Tailwind’s purging, you get tiny bundle sizes:
- 0 KB JS on static pages
- < 5 KB for interactive components
- Perfect Lighthouse scores out of the box
Conclusion
This stack gives you the best of both worlds: a fast, static site with rich interactivity where you need it. The full source code for this portfolio is available on my GitHub.