Next.js Portfolio Framework
Production-ready portfolio framework with MDX content management and advanced theming
Project Tags
A Modern Portfolio Framework for Developers & Designers
A comprehensive, production-ready portfolio framework built with Next.js 14+ that combines powerful content management, advanced theming, and performance optimization. Designed for developers and designers who want a sophisticated portfolio without starting from scratch.
Motivation
After building numerous custom portfolios for clients and myself, I noticed recurring patterns and requirements:
- Content Management: Need for easy content updates without rebuilding
- Performance: Must achieve excellent Lighthouse scores
- Flexibility: Support for different industries and personal brands
- Developer Experience: Smooth local development and deployment
- Accessibility: WCAG AA compliance out of the box
Rather than reinventing the wheel each time, I created a framework that addresses these needs systematically.
Key Features
1. MDX-Powered Content Management
Seamless content authoring with MDX supporting custom components:
---
title: "My Latest Project"
date: "2024-01-15"
tags: ["React", "TypeScript", "AI"]
featured: true
---
# Project Overview
This project demonstrates advanced **AI integration** with React applications.
<TechStack items={["React", "TypeScript", "OpenAI", "Next.js"]} />
<Stats>
<Stat label="Performance" value="98" suffix="/100" />
<Stat label="Users" value="10K" suffix="+" />
</Stats>
<Callout type="success">
Successfully deployed to production with zero downtime!
</Callout>
2. Advanced Theming System
Dual theme support with extensive customization options:
// Theme configuration
export const themes = {
professional: {
colors: {
primary: 'oklch(60% 0.15 240)', // Deep blue
accent: 'oklch(75% 0.20 280)' // Purple accent
},
fonts: {
display: ['Inter', 'system-ui'],
body: ['Inter', 'system-ui']
},
animations: {
duration: 'normal', // 250ms
easing: 'ease-out'
}
},
creative: {
colors: {
primary: 'oklch(65% 0.20 280)', // Vibrant purple
accent: 'oklch(70% 0.25 320)' // Pink accent
},
fonts: {
display: ['Clash Display', 'system-ui'],
body: ['Inter', 'system-ui']
},
animations: {
duration: 'slow', // 400ms
easing: 'cubic-bezier(0.68, -0.55, 0.265, 1.55)' // Bouncy
}
}
} as const
3. Performance-First Architecture
Built-in optimizations for superior performance:
// Automatic image optimization
import { OptimizedImage } from '@/components/OptimizedImage'
const ProjectCard = ({ project }: { project: Project }) => {
return (
<Card>
<OptimizedImage
src={project.coverImage}
alt={project.title}
width={400}
height={240}
priority={project.featured}
placeholder="blur"
blurDataURL={project.blurDataURL}
/>
<CardContent>
<h3>{project.title}</h3>
<p>{project.description}</p>
</CardContent>
</Card>
)
}
4. Accessibility-First Components
All components built with accessibility as a priority:
// Accessible navigation with keyboard support
const Navigation = () => {
const [isOpen, setIsOpen] = useState(false)
const trapFocusRef = useRef<HTMLDivElement>(null)
useFocusTrap(trapFocusRef, isOpen)
useEscapeKey(() => setIsOpen(false))
return (
<nav role="navigation" aria-label="Main navigation">
<button
type="button"
aria-expanded={isOpen}
aria-controls="navigation-menu"
onClick={() => setIsOpen(!isOpen)}
>
<span className="sr-only">
{isOpen ? 'Close navigation' : 'Open navigation'}
</span>
<MenuIcon />
</button>
<div
ref={trapFocusRef}
id="navigation-menu"
className={cn(
'navigation-menu',
isOpen && 'navigation-menu--open'
)}
>
{navigationItems.map((item) => (
<NavigationLink
key={item.href}
href={item.href}
onClick={() => setIsOpen(false)}
>
{item.label}
</NavigationLink>
))}
</div>
</nav>
)
}
Technical Architecture
Content Layer
Flexible content management supporting multiple content types:
// Content schema with Zod validation
export const ProjectSchema = z.object({
title: z.string(),
description: z.string(),
year: z.number(),
stack: z.array(z.string()),
tags: z.array(z.string()),
repo: z.string().url().optional(),
demo: z.string().url().optional(),
status: z.enum(['alpha', 'beta', 'stable', 'archived']),
featured: z.boolean().default(false),
published: z.boolean().default(true)
})
export type Project = z.infer<typeof ProjectSchema>
// Content loading with caching
export const getAllProjects = cache((): ProjectWithContent[] => {
const projectFiles = fs.readdirSync(path.join(process.cwd(), 'content/projects'))
return projectFiles
.filter(file => file.endsWith('.mdx'))
.map(file => {
const slug = file.replace(/\.mdx$/, '')
return parseProject(slug)
})
.filter(project => project.frontMatter.published)
.sort((a, b) => b.frontMatter.year - a.frontMatter.year)
})
Component System
Modular component library with consistent APIs:
// Base card component with variants
interface CardProps extends React.HTMLAttributes<HTMLDivElement> {
variant?: 'default' | 'elevated' | 'outlined'
interactive?: boolean
children: React.ReactNode
}
export const Card = forwardRef<HTMLDivElement, CardProps>(
({ className, variant = 'default', interactive = false, ...props }, ref) => {
return (
<div
ref={ref}
className={cn(
'card',
`card--${variant}`,
interactive && 'card--interactive',
className
)}
{...props}
/>
)
}
)
Build & Deployment Pipeline
Automated quality checks and deployment:
# GitHub Actions workflow
name: Build and Deploy
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
quality-checks:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '18'
cache: 'pnpm'
- run: pnpm install --frozen-lockfile
- run: pnpm typecheck
- run: pnpm lint
- run: pnpm test
- run: pnpm build
- name: Lighthouse CI
run: pnpm lighthouse-ci
env:
LHCI_GITHUB_APP_TOKEN: ${{ secrets.LHCI_GITHUB_APP_TOKEN }}
deploy:
needs: quality-checks
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main'
steps:
- name: Deploy to Vercel
uses: amondnet/vercel-action@v25
with:
vercel-token: ${{ secrets.VERCEL_TOKEN }}
vercel-org-id: ${{ secrets.ORG_ID }}
vercel-project-id: ${{ secrets.PROJECT_ID }}
Performance Optimization
Core Web Vitals Focus
Achieved excellent performance metrics through optimization:
Image Optimization Strategy
// Automatic next/image configuration
const nextConfig = {
images: {
domains: ['images.unsplash.com', 'avatars.githubusercontent.com'],
formats: ['image/webp', 'image/avif'],
sizes: '(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw',
}
}
// Dynamic image loading with blur placeholders
export async function generateBlurDataURL(imageUrl: string): Promise<string> {
const response = await fetch(imageUrl)
const buffer = await response.arrayBuffer()
const base64 = Buffer.from(buffer).toString('base64')
return `data:image/jpeg;base64,${base64}`
}
Bundle Optimization
// Dynamic imports for code splitting
const LazyChart = dynamic(() => import('@/components/Chart'), {
loading: () => <ChartSkeleton />,
ssr: false
})
// Lazy loading of heavy components
const DragExploreGrid = dynamic(() => import('@/components/DragExploreGrid'), {
loading: () => <GridSkeleton />,
ssr: false
})
Developer Experience
Type Safety
Comprehensive TypeScript coverage with strict configuration:
// Strict tsconfig.json
{
"compilerOptions": {
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": true,
"exactOptionalPropertyTypes": true,
"noUncheckedIndexedAccess": true
}
}
// Type-safe content loading
export function getProject(slug: string): ProjectWithContent | null {
try {
const project = parseMarkdownFile('projects', slug, ProjectSchema)
return project
} catch (error) {
console.error(`Failed to load project: ${slug}`, error)
return null
}
}
Development Tools
Comprehensive development setup:
{
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start",
"lint": "next lint",
"lint:fix": "next lint --fix",
"typecheck": "tsc --noEmit",
"test": "vitest",
"test:coverage": "vitest --coverage",
"test:e2e": "playwright test",
"format": "prettier --write .",
"validate-content": "tsx scripts/validate-content.ts"
}
}
Community & Adoption
The framework has gained traction in the developer community:
GitHub Metrics
- Stars: 234+
- Forks: 45+
- Contributors: 12
- Issues Resolved: 89%
Community Contributions
- Template variations for different industries
- Additional theme presets
- Custom component contributions
- Documentation improvements
- Translation support
User Testimonials
"Finally, a portfolio framework that doesn't compromise on performance or accessibility. The MDX integration is seamless." - Frontend Developer
"Used this as the foundation for my design portfolio. The theming system made customization effortless." - UI Designer
"The built-in accessibility features saved me weeks of work. Everything just works." - Accessibility Consultant
Future Roadmap
Planned Features
- CMS Integration: Headless CMS adapters for non-technical users
- Multi-language Support: i18n implementation with automatic routing
- Analytics Dashboard: Built-in performance and visitor analytics
- Component Marketplace: Shareable custom components
- CLI Tool: Project scaffolding and content generation utilities
Community Requests
- WordPress migration tool
- Notion content sync
- Advanced animation presets
- E-commerce integration for selling digital products
- Social media automation
Technical Innovation
1. Adaptive Theme System
Dynamic theme switching with CSS custom properties:
export function useTheme() {
const [theme, setTheme] = useState<ThemeName>('professional')
useEffect(() => {
const root = document.documentElement
const themeConfig = getTheme(theme)
// Apply CSS custom properties
Object.entries(generateCSSVariables(themeConfig)).forEach(([prop, value]) => {
root.style.setProperty(prop, value)
})
// Set data attribute for theme-specific styling
root.setAttribute('data-theme', theme)
}, [theme])
return { theme, setTheme }
}
2. Content Validation Pipeline
Automated content validation with detailed error reporting:
export async function validateAllContent(): Promise<ValidationReport> {
const report = new ValidationReport()
try {
// Validate projects
const projects = await getAllProjects()
projects.forEach(project => {
const result = ProjectSchema.safeParse(project.frontMatter)
if (!result.success) {
report.addError('projects', project.slug, result.error)
}
})
// Validate images exist
const imageValidation = await validateImages(projects)
report.merge(imageValidation)
// Validate external links
const linkValidation = await validateExternalLinks(projects)
report.merge(linkValidation)
} catch (error) {
report.addCriticalError(error as Error)
}
return report
}
3. Progressive Enhancement
Features that work without JavaScript:
// Server-side rendering with progressive enhancement
export default function ProjectsPage({ projects }: { projects: Project[] }) {
return (
<div>
{/* Works without JavaScript */}
<ProjectGrid projects={projects} />
{/* Enhanced with JavaScript */}
<ClientOnly>
<ProjectFilters />
<ProjectSearch />
</ClientOnly>
</div>
)
}
Open Source Philosophy
This project embodies open source best practices:
- Comprehensive Documentation: Detailed setup and customization guides
- Clear Contributing Guidelines: Welcoming to contributors of all levels
- Semantic Versioning: Predictable release cycles
- Backwards Compatibility: Thoughtful breaking changes with migration guides
- Community-Driven: Features prioritized based on community feedback
The framework is MIT licensed and available for both personal and commercial use. Contributions are welcome and encouraged!
Explore More Projects
Discover more open source tools, frameworks, and experiments that solve real-world problems with modern technologies.