Crafting a Dynamic Portfolio Module for Divi: A Step by Step Developer Guide

Crafting a Dynamic Portfolio Module for Divi: A Step by Step Developer Guide

With Divi’s robust API developers can create custom modules that blend seamlessly into the builder experience. In this tutorial we’ll build a Portfolio Module that displays projects from a custom post type (CPT) complete with live previews in the Divi Builder.

Prerequisites

  1. A WordPress site with the Divi theme activated.
  2. CPT UI plugin installed (to create the "Portfolio" CPT).
  3. Basic knowledge of PHP, React, and WordPress REST API.


Part 1: PHP Setup – Frontend Rendering

Step 1: Scaffold a Divi Extension Plugin

Create a plugin directory for your module using Divi’s extension generator:

npx create-divi-extension divi-portfolio-module          

This generates boilerplate code for a Divi module plugin.

Step 2: Define the Portfolio Module Class

Navigate to includes/modules/ and create a Portfolio folder. Inside it, add Portfolio.php:

<?php  
class Portfolio extends ET_Builder_Module {  
    public $slug = 'divi_portfolio';  
    public $vb_support = 'on';  

    public function init() {  
        $this->name = esc_html__('Portfolio', 'divi-portfolio');  
        // Enqueue CSS  
        add_action('wp_enqueue_scripts', [$this, 'enqueue_styles']);  
    }  

    public function enqueue_styles() {  
        wp_enqueue_style(  
            'divi-portfolio-css',  
            plugin_dir_url(__FILE__) . 'portfolio.css'  
        );  
    }  

    public function get_fields() {  
        return [  
            'heading' => [  
                'label' => esc_html__('Heading', 'divi-portfolio'),  
                'type' => 'text',  
                'toggle_slug' => 'main_content',  
            ],  
            'subtitle' => [  
                'label' => esc_html__('Subtitle', 'divi-portfolio'),  
                'type' => 'text',  
                'toggle_slug' => 'main_content',  
            ],  
        ];  
    }  

    public function get_projects() {  
        $query = new WP_Query([  
            'post_type' => 'portfolio',  
            'posts_per_page' => -1  
        ]);  

        $output = '';  
        foreach ($query->posts as $project) {  
            $image = wp_get_attachment_image_src(  
                get_post_thumbnail_id($project->ID),  
                'full'  
            );  
            $output .= sprintf(  
                '<div class="portfolio-item">  
                    <img src="%s" alt="%s">  
                    <h3>%s</h3>  
                    <p>%s</p>  
                </div>',  
                esc_url($image[0]),  
                esc_attr(get_the_title($project->ID)),  
                esc_html(get_the_title($project->ID)),  
                esc_html(get_post_meta($project->ID, 'client_name', true))  
            );  
        }  
        return $output;  
    }  

    public function render($attrs, $content, $render_slug) {  
        return sprintf(  
            '<section class="divi-portfolio">  
                <h2 class="portfolio-heading">%s</h2>  
                <p class="portfolio-subtitle">%s</p>  
                <div class="portfolio-grid">%s</div>  
            </section>',  
            esc_html($this->props['heading']),  
            esc_html($this->props['subtitle']),  
            $this->get_projects()  
        );  
    }  
}  

new Portfolio();          

Step 3: Style the Portfolio Grid

Create portfolio.css in the same folder:

.divi-portfolio {  
    padding: 4rem 0;  
}  

.portfolio-grid {  
    display: grid;  
    grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));  
    gap: 2rem;  
    margin-top: 2rem;  
}  

.portfolio-item img {  
    width: 100%;  
    height: 250px;  
    object-fit: cover;  
    border-radius: 8px;  
}  

.portfolio-item h3 {  
    margin: 1rem 0 0.5rem;  
}          

Part 2: React Integration – Builder Preview

Step 1: Create the React Component

Add Portfolio.jsx to your plugin’s src folder:

import React, { Component } from 'react';  
import './portfolio.css';  

export default class Portfolio extends Component {  
    static slug = 'divi_portfolio';  

    state = {  
        projects: []  
    };  

    componentDidMount() {  
        fetch('/wp-json/wp/v2/portfolio?per_page=100')  
            .then(res => res.json())  
            .then(projects => this.setState({ projects }))  
            .catch(console.error);  
    }  

    render() {  
        const { heading, subtitle } = this.props;  
        return (  
            <section className="divi-portfolio">  
                <h2 className="portfolio-heading">{heading}</h2>  
                <p className="portfolio-subtitle">{subtitle}</p>  
                <div className="portfolio-grid">  
                    {this.state.projects.map(project => (  
                        <div key={project.id} className="portfolio-item">  
                            <img  
                                src={project.featured_media_src_url}  
                                alt={project.title.rendered}  
                            />  
                            <h3>{project.title.rendered}</h3>  
                            <p>{project.meta.client_name}</p>  
                        </div>  
                    ))}  
                </div>  
            </section>  
        );  
    }  
}          

Step 2: Expose Custom Fields to REST API

Ensure portfolio posts expose the client_name meta field and featured images. Add this to your theme’s functions.php:

add_action('rest_api_init', function() {  
    register_rest_field('portfolio', 'client_name', [  
        'get_callback' => function($post) {  
            return get_post_meta($post['id'], 'client_name', true);  
        }  
    ]);  

    register_rest_field('portfolio', 'featured_media_src_url', [  
        'get_callback' => function($post) {  
            return get_the_post_thumbnail_url($post['id'], 'full');  
        }  
    ]);  
});          

Step 3: Build and Activate

Run yarn build to compile your React code, then activate your plugin in WordPress.

Final Result

  1. In the Divi Builder: Drag your new "Portfolio" module into a layout. Configure the heading and subtitle.
  2. Frontend: Visitors see a responsive grid of portfolio projects, each displaying the title, client name, and image.

Why This Matters

  • Reusability: Use the module across any Divi site.
  • Performance: Server-side rendering (PHP) ensures fast page loads, while React keeps the builder experience dynamic.
  • Scalability: Easily extend the module with filters, pagination, or AJAX loading.

Next-Level Enhancements

  1. Add a category filter using Divi’s select field and taxonomy queries.
  2. Implement lightbox popups for project images.
  3. Use wp-cron to auto-refresh cached projects hourly.

Dive into Divi’s API documentation to unlock even more possibilities.

Happy coding and may your portfolios turn heads and land clients! ??

Clinton Moses

Software Developer | React engineer | Tech advocate

1 周

Very helpful Amakiri John Lucky

回复

要查看或添加评论,请登录

Amakiri John Lucky的更多文章

社区洞察

其他会员也浏览了