DEV Community

OTHMANE IBN DAHOU IDRISSI
OTHMANE IBN DAHOU IDRISSI

Posted on

From Elementor to Headless: How I Rebuilt My Portfolio with React and WordPress GraphQL

 The Challenge: Breaking Free from Page Builders

After years of building websites with Elementor and traditional WordPress themes, I decided to challenge myself with a complete portfolio rebuild using modern web technologies. The goal? Create a blazing-fast, scalable portfolio that separates content management from presentation while maintaining the flexibility WordPress offers.

What I built: A fully decoupled headless WordPress architecture with React powering the frontend.

Live URLs:


Why I Made the Switch

The Limitations I Faced with Elementor

Don't get me wrong - Elementor is powerful and I've built countless successful sites with it. But as my skills evolved, I started hitting walls:

  1. Performance bottlenecks - Heavy page builders load lots of CSS/JS even when unused
  2. Limited customization - Want something truly custom? You're writing CSS overrides everywhere
  3. Scaling issues - Managing 100+ pages with Elementor can get sluggish
  4. Modern development - No access to React ecosystem, component libraries, or modern build tools
  5. Mobile experience - While responsive, the mobile experience wasn't as snappy as I wanted

What I Gained with Headless WordPress

The headless approach solved these issues:

Lightning-fast performance - React optimizes rendering, Vite builds are tiny
Complete design freedom - Build ANY UI without fighting CSS specificity
Modern developer experience - React hooks, component libraries, TypeScript support
Scalability - Frontend and backend scale independently
Future-proof - Can swap frontend framework without touching content


The Technical Architecture

Backend: WordPress as a Headless CMS

What I kept:

  • WordPress Admin for content management
  • Custom Post Types (Portfolio, Blog)
  • Advanced Custom Fields for structured data
  • Media Library for asset management

What changed:

  • Removed ALL themes (using default WordPress)
  • Removed page builders completely
  • Exposed data via WPGraphQL instead of REST API
  • Created custom REST endpoints for contact form

Key plugins used:

  • WPGraphQL - Exposes WordPress data via GraphQL
  • WPGraphQL for ACF - Makes custom fields queryable
  • Custom Post Type UI - Creates custom post types
  • Advanced Custom Fields - Structures data

Why GraphQL over REST?

  • Fetch exactly what you need (no over/under-fetching)
  • Single endpoint for all queries
  • Strongly typed schema
  • Better developer experience with GraphiQL

Frontend: React with Vite

Tech stack:

  • React 18 - UI library
  • Vite - Build tool (faster than Create React App)
  • Apollo Client - GraphQL data fetching
  • React Router - Client-side routing
  • Swiper - Carousels/sliders
  • CSS Variables - Dynamic theming

Why Vite over Create React App?

  • 10-100x faster hot module replacement
  • Instant server start
  • Optimized production builds
  • Better developer experience

The Migration Process: Step by Step

Phase 1: Planning (1 week)

I audited my existing Elementor site:

  • Mapped out all pages and sections
  • Identified reusable components
  • Planned data structure in WordPress
  • Created wireframes for new design

Phase 2: WordPress Setup (3 days)

  1. Created custom post types (Portfolio, Services)
  2. Set up Advanced Custom Fields
  3. Installed and configured WPGraphQL
  4. Migrated content from old site
  5. Created custom REST endpoint for contact form
  6. Tested GraphQL queries in GraphiQL

Sample GraphQL query:

query GetPortfolio {
  portfolio {
    nodes {
      title
      content
      featuredImage {
        node {
          sourceUrl
        }
      }
      portfolioDetails {
        projectUrl
        technologies
        clientName
      }
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Phase 3: React Development (2 weeks)

Component structure I built:

  • Navbar with mobile menu & dark mode toggle
  • Hero section with animations
  • About section with stats
  • Services grid (9 services)
  • Experience/Education timeline
  • Skills with animated progress bars
  • Blog list with category filtering
  • Single blog post with related posts carousel
  • Portfolio grid with modal details
  • Contact form with WordPress integration
  • Footer with social links

Key features implemented:

  • Dark/Light mode toggle (persists in localStorage)
  • Responsive design (mobile-first approach)
  • Smooth animations and transitions
  • SEO-friendly routing
  • Form validation and error handling
  • Loading states and error boundaries

Phase 4: Integration & Testing (1 week)

  1. Connected Apollo Client to WordPress GraphQL
  2. Implemented CORS handling
  3. Tested all queries and mutations
  4. Fixed edge cases and bugs
  5. Optimized images and assets
  6. Performance testing (Lighthouse)

Phase 5: Deployment (2 days)

Backend (WordPress):

  • Deployed to api.othmanewp.com
  • Configured SSL and CORS headers
  • Set up caching and security
  • Enabled GraphQL introspection

Frontend (React):

  • Built production bundle with Vite
  • Deployed to othmanewp.com
  • Configured routing and redirects
  • Set up analytics

The Results: Performance Comparison

Before (Elementor)

  • First Contentful Paint: ~2.8s
  • Time to Interactive: ~5.2s
  • Total Bundle Size: ~890KB
  • Lighthouse Score: 72/100

After (Headless React)

  • First Contentful Paint: ~0.8s ✅ (65% faster)
  • Time to Interactive: ~1.4s ✅ (73% faster)
  • Total Bundle Size: ~180KB ✅ (80% smaller)
  • Lighthouse Score: 96/100 ✅

Other improvements:

  • Mobile experience is significantly smoother
  • Navigation feels instant (client-side routing)
  • Dark mode toggle is instant
  • No layout shifts or jank
  • Better SEO with proper meta tags

Challenges I Faced (And How I Solved Them)

Challenge 1: Learning Curve

Problem: GraphQL was completely new to me

Solution:

  • Spent time in GraphiQL playground
  • Started with simple queries, built complexity gradually
  • Used Apollo Client DevTools for debugging
  • Followed WPGraphQL documentation

Challenge 2: CORS Issues

Problem: React couldn't fetch from WordPress due to CORS

Solution:
Added headers to wp-config.php:

header('Access-Control-Allow-Origin: https://othmanewp.com');
header('Access-Control-Allow-Methods: GET, POST, OPTIONS');
header('Access-Control-Allow-Headers: Content-Type, Authorization');
Enter fullscreen mode Exit fullscreen mode

Challenge 3: Contact Form

Problem: No traditional form plugin support in headless setup

Solution:
Created custom WordPress REST API endpoint:

  • Validates and sanitizes form data
  • Sends email via wp_mail()
  • Saves to database
  • Returns JSON response to React

Challenge 4: Image Optimization

Problem: Large images from WordPress slowing down React app

Solution:

  • Used WordPress image sizes (thumbnail, medium, large)
  • Implemented lazy loading in React
  • Added loading="lazy" attribute
  • Optimized images before upload

Challenge 5: SEO Concerns

Problem: Client-side rendering can hurt SEO

Solution (for now):

  • Proper meta tags in HTML
  • Semantic HTML structure
  • Fast page loads (good for SEO)

Future improvement: Consider Next.js for SSR/SSG


Code Quality & Best Practices

React Component Structure

components/
├── Navbar.jsx          # Reusable navigation
├── Footer.jsx          # Site footer
├── Hero.jsx            # Homepage hero
├── Blog.jsx            # Blog preview section
└── [...]

pages/
├── Home.jsx            # Homepage (combines components)
├── Blog.jsx            # Blog list page
├── BlogPost.jsx        # Single post page
├── Portfolio.jsx       # Portfolio grid
└── Contact.jsx         # Contact form
Enter fullscreen mode Exit fullscreen mode

State Management

  • Used React Context for theme (dark/light mode)
  • Apollo Client cache for GraphQL data
  • Local state for forms and UI interactions

Styling Approach

  • CSS Modules for component styles
  • CSS Variables for theming
  • Mobile-first responsive design
  • No CSS framework (custom styles)

What I Learned

Technical Skills

  1. GraphQL - Query language and how it differs from REST
  2. Apollo Client - Data fetching, caching, state management
  3. Headless CMS architecture - Separation of concerns
  4. Modern React patterns - Hooks, Context, custom hooks
  5. Build optimization - Vite, code splitting, lazy loading
  6. WordPress as API - Using WordPress beyond themes

Soft Skills

  1. Planning is crucial - Spent 20% time planning, saved 50% dev time
  2. Documentation matters - Good docs = faster development
  3. Performance first - Think about performance from day one
  4. User experience - Speed matters more than fancy features
  5. Iteration works - Build, test, improve, repeat

Should You Go Headless?

When Headless Makes Sense ✅

  • You need maximum performance
  • You want modern development workflow
  • You're comfortable with JavaScript
  • You need to scale frontend/backend separately
  • You want to use modern frameworks (React, Vue, Next.js)
  • You have complex, custom requirements

When to Stick with Traditional WordPress ⚠️

  • You need a site up quickly (hours, not weeks)
  • Your team isn't technical (prefers visual builders)
  • You need WordPress plugins that modify frontend
  • Simple blog or brochure site
  • Limited development resources
  • SEO is absolutely critical (consider Next.js if going headless)

Future Plans

I'm not done yet! Here's what's next:

Short-term:

  • [ ] Add search functionality
  • [ ] Implement comments system
  • [ ] Add social sharing
  • [ ] Create sitemap generator
  • [ ] Add reading time to posts

Long-term:

  • [ ] Migrate to Next.js for SSR/SSG
  • [ ] Add internationalization (i18n)
  • [ ] Implement advanced analytics
  • [ ] Create admin dashboard for stats
  • [ ] Add progressive web app (PWA) features

Resources That Helped Me

Official Docs:

Communities:

  • WPGraphQL Slack
  • React Discord
  • Stack Overflow
  • WordPress Forums

Tools:

  • GraphiQL (GraphQL playground)
  • Apollo DevTools (Chrome extension)
  • React DevTools
  • Lighthouse (performance testing)

Key Takeaways

  1. Headless WordPress is powerful but requires more technical knowledge than traditional WordPress
  2. Performance gains are real - My site is 3-4x faster than with Elementor
  3. Development experience matters - Modern tools make coding more enjoyable
  4. It's not for everyone - Assess your needs before jumping in
  5. The learning curve is worth it - Skills are transferable to other projects

The Numbers

Time Investment:

  • Planning & design: 1 week
  • WordPress setup: 3 days
  • React development: 2 weeks
  • Testing & deployment: 1 week
  • Total: ~4 weeks

Lines of Code:

  • React components: ~3,500 lines
  • CSS: ~2,800 lines
  • WordPress custom code: ~400 lines
  • Total: ~6,700 lines

Performance Improvement:

  • 73% faster time to interactive
  • 80% smaller bundle size
  • 96/100 Lighthouse score

Conclusion

Migrating from Elementor to a headless WordPress + React architecture was challenging but incredibly rewarding. I now have a portfolio that's:

  • ⚡ Lightning fast
  • 🎨 Completely custom designed
  • 📱 Perfectly responsive
  • 🚀 Easy to maintain and scale
  • 💪 Built with modern best practices

Would I do it again? Absolutely. The skills I learned are applicable to any modern web project, and the performance gains speak for themselves.

Would I recommend it to everyone? No. If you're happy with Elementor and it meets your needs, stick with it. But if you're ready to level up your development skills and want maximum control over your site, going headless is an exciting journey.


Check It Out

Live Demo:

Open to feedback! What would you like to know about the migration process? Have you considered going headless? Drop your questions in the comments!


Tags: #WebDevelopment #WordPress #React #Headless #GraphQL #Frontend #ModernWeb #Performance #Elementor #Migration


About Me:
I'm a WordPress Developer specializing in headless architectures, custom theme development, and modern JavaScript frameworks. Currently working with React, Laravel, and Tailwind CSS to build fast, scalable web applications.

Connect with me:


Have you migrated from a page builder to a headless setup? I'd love to hear about your experience!

Top comments (0)