Crafting a Dynamic Portfolio Module for Divi: A Step by Step Developer Guide
Amakiri John Lucky
WordPress Development | Custom Solutions | AI Integration | Technical Leadership | "Recognised for surpassing expectations & achieving what seemed improbable"
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
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
Why This Matters
Next-Level Enhancements
Dive into Divi’s API documentation to unlock even more possibilities.
Happy coding and may your portfolios turn heads and land clients! ??
Software Developer | React engineer | Tech advocate
1 周Very helpful Amakiri John Lucky