Inspiration
As developers, we all need portfolios—but most are static HTML sites that require code changes for every content update. Want to add a new project? Edit HTML. Update your bio? Modify JSX. Fix a typo? Redeploy.
I wanted a solution that combines the speed of static sites with the flexibility of a CMS—without the overhead of a backend, database, or admin authentication. DynamicFolio CMS was born from this need: a fully dynamic portfolio that stores data in localStorage, making it perfect for single-user portfolios that need frequent updates.
The DevOne Hack theme ("Build Your Developer Portfolio") was the perfect catalyst to turn this idea into reality.
What it does
DynamicFolio CMS is a Next.js 16 portfolio website with a built-in admin dashboard that lets you:
✅ **Manage all content** (Hero, About, Projects, Skills, Blog, Resume, Testimonials) through an intuitive UI
✅ **Integrate real Medium blog posts** via RSS feeds (auto-fetches on page load)
✅ **Support 6 languages** (English, Spanish, French, Chinese, Arabic, Bengali) with RTL for Arabic
✅ **Generate print-optimized PDF resumes** with one click
✅ **Drag-and-drop reorder** projects, skills, and experiences
✅ **Preview changes in real-time** without page reloads
✅ **Store all data in localStorage**—no backend, no database, no authentication needed
The admin dashboard (/admin) provides a complete CMS experience with form validation, toast notifications, and persistent state management using Zustand.
How we built it
Tech Stack:
- Next.js 16 (App Router + Turbopack) for ultra-fast builds
- TypeScript 5.0 in strict mode for type safety
- Zustand with localStorage persistence for state management
- Tailwind CSS + Shadcn UI for beautiful, accessible components
- Framer Motion for smooth animations
- rss-parser for Medium RSS integration
- @hello-pangea/dnd for drag-and-drop functionality
Architecture:
- Server-first design: Default to Server Components, use
"use client"only when needed - Co-located features: Each route has
_components/,_hooks/,_services/subfolders - Modular stores: Separate Zustand stores for hero, about, projects, skills, blog, resume, testimonials
- Custom i18n system: Context-based translations with 600+ keys across 6 languages
- Print optimization: Dedicated
/resume/printroute with inline CSS for PDF export
Key Technical Decisions:
- No Backend: localStorage persistence removes need for database, hosting, authentication
- Server-side RSS: Solved CORS issues by creating
/api/blog/fetch-mediumAPI route - Auto-fetch logic: Blog page detects placeholder text and automatically refreshes Medium posts
- Hydration pattern: Custom
useHydration()hook prevents SSR/client mismatches
Challenges we ran into
1. CORS Issues with Medium RSS
- Problem: Direct fetch from Medium RSS failed due to CORS policy
- Solution: Created server-side API route (
/api/blog/fetch-medium) to proxy requests - Learning: Server-side fetching avoids browser CORS restrictions
2. SSR/Client Hydration Mismatches
- Problem: Zustand loads localStorage data on client, causing "Hydration failed" errors
- Solution: Built
useHydration()hook that waits for client hydration before rendering - Learning: Always check if data is hydrated before accessing stores in Server Components
3. Auto-Fetch for External Blog Posts
- Problem: Blog page showed placeholder until manual "Refresh Feeds" click
- Solution: Added smart detection in
use-blog-data.tshook to auto-fetch on mount - Learning: Detect existing data to avoid unnecessary API calls
4. RTL Layout for Arabic
- Problem: Arabic text broke layout, icons mirrored incorrectly
- Solution: Used
dirattribute from i18n context + Tailwindrtl:modifier - Learning: RTL support requires both HTML dir attribute and CSS logical properties
5. Print-Optimized Resume
- Problem: Browser print dialog included navigation, footers, and broke pagination
- Solution: Created dedicated
/resume/printroute with inline CSS and print-specific styles - Learning: Inline styles ensure consistent rendering across browsers
Accomplishments that we're proud of
✅ Built a **full-featured CMS without a single line of backend code**
✅ Integrated **real Medium RSS feeds** with automatic excerpt extraction from HTML
✅ Implemented **6-language support** including RTL (Arabic) with 600+ translation keys
✅ Achieved **0 TypeScript errors** in strict mode across 23 production routes
✅ Designed **intuitive drag-and-drop admin interface** with real-time preview
✅ Created **print-optimized resume route** that generates pixel-perfect PDFs
✅ Maintained **server-first architecture** with minimal client-side JavaScript
✅ Completed entire project from idea to deployment in hackathon timeline
What we learned
Technical Skills:
- Next.js 16 App Router: Mastered server components, streaming, and route groups
- State Management: Built complex Zustand stores with localStorage persistence
- RSS Parsing: Learned XML parsing, HTML extraction, and graceful error handling
- SSR Patterns: Solved hydration issues with custom hooks and client/server boundaries
- Internationalization: Designed scalable i18n system supporting RTL languages
- Performance: Implemented lazy loading, Suspense boundaries, and React Compiler optimizations
Product Design:
- Importance of intuitive UX: Admin dashboard must be as simple as editing a Google Doc
- Progressive disclosure: Show only what's needed; hide complexity behind smart defaults
- Real-time feedback: Toast notifications and instant preview prevent user confusion
Engineering Process:
- Start with Server Components by default, add
"use client"only when needed - Co-locate features for maintainability (avoid giant
/componentsfolder) - Use barrel exports (
index.ts) for clean imports - Separate data, types, and logic for loose coupling
What's next for DynamicFolio CMS
Short-term (Post-Hackathon):
- Analytics dashboard to track portfolio views, project clicks, blog engagement
- Contact form integration with SendGrid/Resend for email notifications
- Image upload via Cloudinary/Uploadcare (currently uses static URLs)
Mid-term (1-3 months):
- Export/import data as JSON for backup and migration
- Theme customization: color picker for brand personalization
- SEO enhancements: Open Graph images, structured data, dynamic sitemaps
Long-term (3+ months):
- Optional Supabase backend for multi-user scenarios
- PWA support with offline-first service workers
- AI-powered content suggestions (e.g., "Improve your project descriptions")
- Template marketplace: Share portfolio designs with community
Vision: Make DynamicFolio CMS the go-to solution for developers who want a professional portfolio without the complexity of WordPress or headless CMS platforms. Think "Notion for developer portfolios."
Built With
- framer-motion
- nextjs
- rss-parser
- shadcn-ui
- typescript
- zustand
Log in or sign up for Devpost to join the conversation.