Ep.05: WordPress Plugin Demo Library – Displaying Available Demos

Views: 1

Welcome to Episode 5 of building the Versana Companion plugin! In Episode 4, we integrated our settings into the theme’s options page. Now it’s time to show users what demos are available for import. In this episode, you’ll learn how to create a WordPress plugin demo library – a simple list of available demos that users can browse and import. No database needed! We’ll define our demos directly in PHP and display them in a new “Demo Import” tab.

By the end of this tutorial, you’ll have a professional demo library showing three demos (Business, Blog, Portfolio) with descriptions, preview links, and import buttons.

What We’ll Cover

  1. Why we don’t need a database for static demos
  2. Defining demos in PHP arrays
  3. Adding a Demo Import tab
  4. Displaying demo information
  5. Creating import buttons
  6. Styling the demo grid
  7. Testing the demo library

Prerequisites

  • Completed Episodes 2-4
  • Versana theme and plugin active
  • Text editor open
  • Demo XML files created (from Episode 6)

Part 1: Why No Database?

Understanding Data Storage Needs

When to use database:

  • ✅ User-generated content
  • ✅ Frequently changing data
  • ✅ Need to track statistics
  • ✅ Lots of items (100+)
  • ✅ Need to query/filter/search

When to use PHP arrays:

  • ✅ Fixed, static data
  • ✅ Developer-defined content
  • ✅ Small number of items
  • ✅ Doesn’t change often
  • ✅ Simple structure

Our Demo Library

What we have:

  • 3 fixed demos (Business, Blog, Portfolio)
  • Defined by theme developer (you)
  • Never changes unless you update plugin
  • Simple structure (name, description, preview)
  • No user interaction needed

Perfect for PHP array!

Benefits:

  • ✅ No database queries (faster)
  • ✅ No activation setup needed
  • ✅ Easy to update (edit PHP)
  • ✅ Version controlled (in code)
  • ✅ Simple to understand
  • ✅ No extra tables

Example:

// ❌ Database approach (unnecessary complexity)
CREATE TABLE demos...
INSERT INTO demos...
SELECT * FROM demos...

// ✅ Simple array (perfect for our needs)
$demos = array(
    'business' => array(
        'name' => 'Business',
        'description' => 'Professional business site',
    ),
);

Part 2: Defining Our Demos

Step 1: Create Demo Definitions Function

Add this function to your plugin file:

/**
 * Get available demos
 * 
 * Returns array of available demo configurations
 * 
 * @return array Demos array
 */
function versana_companion_get_available_demos() {
    $demos = array(
        'business' => array(
            'name'        => __( 'Business Website', 'versana-companion' ),
            'description' => __( 'Professional business website with services and portfolio sections. Perfect for corporate sites, agencies, and consultancies.', 'versana-companion' ),
            'preview_url' => 'https://demos.codoplex.com/versana/business/',
            'thumbnail'   => VERSANA_COMPANION_URL . 'assets/images/demos/business.jpg',
            'xml_file'    => VERSANA_COMPANION_PATH . 'demos/business/content.xml',
            'category'    => 'business',
            'tags'        => array( 'business', 'corporate', 'professional' ),
        ),
        'blog' => array(
            'name'        => __( 'Personal Blog', 'versana-companion' ),
            'description' => __( 'Clean and minimal blog layout perfect for writers and content creators. Focus on readability and content.', 'versana-companion' ),
            'preview_url' => 'https://demos.codoplex.com/versana/blog/',
            'thumbnail'   => VERSANA_COMPANION_URL . 'assets/images/demos/blog.jpg',
            'xml_file'    => VERSANA_COMPANION_PATH . 'demos/blog/content.xml',
            'category'    => 'blog',
            'tags'        => array( 'blog', 'minimal', 'writer' ),
        ),
        'portfolio' => array(
            'name'        => __( 'Creative Portfolio', 'versana-companion' ),
            'description' => __( 'Showcase your work with a beautiful portfolio layout. Ideal for designers, photographers, and creative professionals.', 'versana-companion' ),
            'preview_url' => 'https://demos.codoplex.com/versana/portfolio/',
            'thumbnail'   => VERSANA_COMPANION_URL . 'assets/images/demos/portfolio.jpg',
            'xml_file'    => VERSANA_COMPANION_PATH . 'demos/portfolio/content.xml',
            'category'    => 'portfolio',
            'tags'        => array( 'portfolio', 'creative', 'showcase' ),
        ),
    );
    
    /**
     * Filter available demos
     * 
     * Allows adding custom demos via child theme or plugin
     * 
     * @param array $demos Array of demo configurations
     */
    return apply_filters( 'versana_companion_available_demos', $demos );
}

Understanding the structure:

'business' => array( /* ... */ ),
  • Key: 'business' (unique identifier)
  • Value: Array of demo information
  • Key must match XML folder name
'name' => __( 'Business Website', 'versana-companion' ),
  • Display name shown to users
  • __() = Translation function
  • Shows in demo grid
'description' => __( 'Professional business...', 'versana-companion' ),
  • Short description (1-2 sentences)
  • Explains what demo is for
  • Helps users choose
'preview_url' => 'https://demos.codoplex.com/versana/business/',
  • Link to live demo
  • Users can preview before importing
  • Opens in new tab
'thumbnail' => VERSANA_COMPANION_URL . 'assets/images/demos/business.jpg',
  • Screenshot of demo
  • Shows visual preview
  • Using plugin URL constant
'xml_file' => VERSANA_COMPANION_PATH . 'demos/business/content.xml',
  • Path to XML content file
  • Using plugin path constant
  • For import functionality
'category' => 'business',
  • Demo category
  • For future filtering
  • Optional metadata
'tags' => array( 'business', 'corporate', 'professional' ),
  • Demo tags/keywords
  • For future search/filter
  • Optional metadata

Part 3: Adding Demo Import Tab

Step 2: Add Demo Import Tab

Update your tab registration to add a Demo Import tab:

/**
 * Add Companion tabs to theme options
 * 
 * @param array $tabs Existing tabs
 * @return array Modified tabs
 */
function versana_companion_add_settings_tabs( $tabs ) {
    // Demo Import tab (priority 5 - very first)
    $tabs['demo_import'] = array(
        'title'    => __( 'Demo Import', 'versana-companion' ),
        'icon'     => 'dashicons-download',
        'callback' => 'versana_companion_render_demo_import_tab',
        'priority' => 5,
    );
    
    // Companion settings tab (priority 10 - second)
    $tabs['companion'] = array(
        'title'    => __( 'Companion', 'versana-companion' ),
        'icon'     => 'dashicons-admin-plugins',
        'callback' => 'versana_companion_render_settings_tab',
        'priority' => 10,
    );
    
    return $tabs;
}
add_filter( 'versana_option_tabs', 'versana_companion_add_settings_tabs' );

Why two tabs?

  • Demo Import (priority 5) – Shows available demos, import buttons
  • Companion (priority 10) – Plugin settings from Episode 4

Tab order:

[Demo Import] [Companion] [Header] [Footer] [Blog] [...]
     ↑            ↑
   First       Second

Part 4: Displaying the Demo Library

Step 3: Create Demo Library Display

Add this function to render the demo library:

/**
 * Render Demo Import tab
 * 
 * Displays available demos with import functionality
 */
function versana_companion_render_demo_import_tab() {
    // Check if demo import is enabled
    if ( ! versana_companion_get_setting( 'enable_demo_import', true ) ) {
        ?>
        <div class="versana-tab-content">
            <div class="notice notice-warning">
                <p>
                    <?php esc_html_e( 'Demo import is currently disabled. Enable it in the Companion tab.', 'versana-companion' ); ?>
                </p>
            </div>
        </div>
        <?php
        return;
    }
    
    // Get available demos
    $demos = versana_companion_get_available_demos();
    
    ?>
    <div class="versana-tab-content">
        <h2><?php esc_html_e( 'Import Demo Content', 'versana-companion' ); ?></h2>
        <p class="description">
            <?php esc_html_e( 'Choose a demo to import. This will add sample posts, pages, and content to your site.', 'versana-companion' ); ?>
        </p>
        
        <div class="versana-demo-library">
            <?php foreach ( $demos as $demo_key => $demo ) : ?>
                <div class="versana-demo-item">
                    <!-- Demo Thumbnail -->
                    <div class="demo-thumbnail">
                        <?php if ( ! empty( $demo['thumbnail'] ) && file_exists( str_replace( VERSANA_COMPANION_URL, VERSANA_COMPANION_PATH, $demo['thumbnail'] ) ) ) : ?>
                            <img src="<?php echo esc_url( $demo['thumbnail'] ); ?>" 
                                 alt="<?php echo esc_attr( $demo['name'] ); ?>">
                        <?php else : ?>
                            <div class="demo-thumbnail-placeholder">
                                <span class="dashicons dashicons-admin-appearance"></span>
                            </div>
                        <?php endif; ?>
                    </div>
                    
                    <!-- Demo Info -->
                    <div class="demo-info">
                        <h3 class="demo-name"><?php echo esc_html( $demo['name'] ); ?></h3>
                        <p class="demo-description"><?php echo esc_html( $demo['description'] ); ?></p>
                    </div>
                    
                    <!-- Demo Actions -->
                    <div class="demo-actions">
                        <?php if ( ! empty( $demo['preview_url'] ) ) : ?>
                            <a href="<?php echo esc_url( $demo['preview_url'] ); ?>" 
                               class="button" 
                               target="_blank" 
                               rel="noopener noreferrer">
                                <span class="dashicons dashicons-visibility"></span>
                                <?php esc_html_e( 'Preview', 'versana-companion' ); ?>
                            </a>
                        <?php endif; ?>
                        
                        <?php if ( file_exists( $demo['xml_file'] ) ) : ?>
                            <button type="button" 
                                    class="button button-primary versana-import-demo" 
                                    data-demo="<?php echo esc_attr( $demo_key ); ?>">
                                <span class="dashicons dashicons-download"></span>
                                <?php esc_html_e( 'Import', 'versana-companion' ); ?>
                            </button>
                        <?php else : ?>
                            <button type="button" class="button" disabled>
                                <?php esc_html_e( 'File Missing', 'versana-companion' ); ?>
                            </button>
                        <?php endif; ?>
                    </div>
                </div>
            <?php endforeach; ?>
        </div>
        
        <?php if ( empty( $demos ) ) : ?>
            <div class="notice notice-info">
                <p><?php esc_html_e( 'No demos available at this time.', 'versana-companion' ); ?></p>
            </div>
        <?php endif; ?>
    </div>
    <?php
}

Understanding the display:

if ( ! versana_companion_get_setting( 'enable_demo_import', true ) ) {
  • Check if demo import is enabled (from Episode 4 settings)
  • If disabled, show message
  • Respects user’s settings
$demos = versana_companion_get_available_demos();
  • Get demo definitions
  • Returns array we created earlier
foreach ( $demos as $demo_key => $demo ) :
  • Loop through each demo
  • $demo_key = ‘business’, ‘blog’, or ‘portfolio’
  • $demo = Array of demo info
<div class="versana-demo-item">
  • Container for one demo
  • We’ll style this with CSS
<?php if ( ! empty( $demo['thumbnail'] ) && file_exists( ... ) ) : ?>
  • Check if thumbnail exists
  • file_exists() verifies file is actually there
  • Shows placeholder if missing
<img src="<?php echo esc_url( $demo['thumbnail'] ); ?>" 
  • Display thumbnail image
  • esc_url() = Security (escape URL)
data-demo="<?php echo esc_attr( $demo_key ); ?>"
  • Store demo key in data attribute
  • Used by JavaScript for import
  • We’ll add JavaScript in Episode 7
<?php if ( file_exists( $demo['xml_file'] ) ) : ?>
  • Check if XML file actually exists
  • Only show Import button if file is there
  • Shows “File Missing” if not found

Part 5: Adding Basic Styling

Step 4: Create Demo Library CSS

Create file: versana-companion/assets/css/demo-library.css

/**
 * Demo Library Styles
 */

.versana-demo-library {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
    gap: 30px;
    margin-top: 30px;
}

.versana-demo-item {
    background: #fff;
    border: 1px solid #ddd;
    border-radius: 4px;
    overflow: hidden;
    transition: transform 0.2s, box-shadow 0.2s;
}

.versana-demo-item:hover {
    transform: translateY(-5px);
    box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1);
}

.demo-thumbnail {
    position: relative;
    width: 100%;
    padding-bottom: 66.67%; /* 3:2 aspect ratio */
    overflow: hidden;
    background: #f5f5f5;
}

.demo-thumbnail img {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.demo-thumbnail-placeholder {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    display: flex;
    align-items: center;
    justify-content: center;
    background: #f5f5f5;
}

.demo-thumbnail-placeholder .dashicons {
    font-size: 60px;
    width: 60px;
    height: 60px;
    color: #ccc;
}

.demo-info {
    padding: 20px;
}

.demo-name {
    margin: 0 0 10px;
    font-size: 18px;
    font-weight: 600;
}

.demo-description {
    margin: 0;
    color: #666;
    font-size: 14px;
    line-height: 1.6;
}

.demo-actions {
    padding: 0 20px 20px;
    display: flex;
    gap: 10px;
}

.demo-actions .button {
    flex: 1;
    text-align: center;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 5px;
}

.demo-actions .button .dashicons {
    font-size: 16px;
    width: 16px;
    height: 16px;
}

/* Responsive */
@media screen and (max-width: 782px) {
    .versana-demo-library {
        grid-template-columns: 1fr;
    }
}

Step 5: Enqueue CSS

Add this function to load the CSS:

/**
 * Enqueue demo library assets
 * 
 * @param string $hook Current admin page
 */
function versana_companion_enqueue_demo_library_assets( $hook ) {
    // Only on theme options page
    if ( 'appearance_page_versana-options' !== $hook ) {
        return;
    }
    
    // Only if on demo import tab
    $active_tab = isset( $_GET['tab'] ) ? sanitize_text_field( $_GET['tab'] ) : '';
    if ( 'demo_import' !== $active_tab ) {
        return;
    }
    
    // Enqueue CSS
    wp_enqueue_style(
        'versana-companion-demo-library',
        VERSANA_COMPANION_URL . 'assets/css/demo-library.css',
        array(),
        VERSANA_COMPANION_VERSION
    );
}
add_action( 'admin_enqueue_scripts', 'versana_companion_enqueue_demo_library_assets' );

Understanding enqueue:

if ( 'appearance_page_versana-options' !== $hook ) {
  • Only load on theme options page
  • $hook = Current page identifier
  • Saves resources (doesn’t load everywhere)
$active_tab = isset( $_GET['tab'] ) ? sanitize_text_field( $_GET['tab'] ) : '';
  • Get active tab from URL
  • sanitize_text_field() = Security
  • Only load CSS on Demo Import tab
wp_enqueue_style(
    'versana-companion-demo-library',  // Handle (unique ID)
    VERSANA_COMPANION_URL . 'assets/css/demo-library.css',  // File URL
    array(),  // Dependencies (none)
    VERSANA_COMPANION_VERSION  // Version (for cache busting)
);
  • Register and load CSS file
  • Version number updates when plugin updates
  • Breaks browser cache automatically

Part 6: Creating Placeholder Images

Step 6: Add Demo Thumbnails

You need thumbnail images for each demo. Create these files:

versana-companion/
└── assets/
    └── images/
        └── demos/
            ├── business.jpg     (1200x800 recommended)
            ├── blog.jpg         (1200x800 recommended)
            └── portfolio.jpg    (1200x800 recommended)

If you don’t have images yet:

The code already handles missing images! It will show a placeholder icon instead.

To test without images:

  1. Create the folders
  2. Leave them empty for now
  3. Placeholders will show automatically

When you’re ready:

  1. Take screenshots of each demo
  2. Resize to 1200×800 pixels
  3. Save as JPG (optimize for web)
  4. Upload to folders

Part 7: Testing the Demo Library

Test Your Demo Library

1. Go to theme options:

WordPress Admin → Appearance → Theme Options

2. Look for Demo Import tab:

Should see tabs:
[Demo Import] [Companion] [Header] [Footer] [Blog] [...]
      ↑
   NEW TAB! (first position)

3. Click Demo Import tab:

Should show:
- Grid layout (3 demos)
- Thumbnails or placeholders
- Demo names and descriptions
- Preview and Import buttons

4. Verify each demo shows:

✓ Business Website
   - Description visible
   - Preview button links to demo URL
   - Import button enabled (if XML exists)

✓ Personal Blog
   - Description visible
   - Buttons present

✓ Creative Portfolio
   - Description visible
   - Buttons present

5. Test if settings work:

a) Go to Companion tab
b) Uncheck "Enable Demo Import"
c) Save Settings
d) Go back to Demo Import tab
e) Should show: "Demo import is currently disabled"
f) Re-enable and test again

6. Test preview links:

Click "Preview" button
- Should open in new tab
- Should go to demo URL
- User can see live demo

7. Check responsive:

Resize browser window
- Should show 1 column on mobile
- Grid should adapt nicely

Part 8: Getting Single Demo Info

Step 7: Helper Function for Single Demo

Add helper to get specific demo:

/**
 * Get single demo information
 * 
 * @param string $demo_key Demo identifier
 * @return array|null Demo data or null if not found
 */
function versana_companion_get_demo( $demo_key ) {
    $demos = versana_companion_get_available_demos();
    return isset( $demos[ $demo_key ] ) ? $demos[ $demo_key ] : null;
}

Usage:

// Get business demo
$demo = versana_companion_get_demo( 'business' );

if ( $demo ) {
    echo 'Name: ' . $demo['name'];
    echo 'File: ' . $demo['xml_file'];
    
    // Check if file exists
    if ( file_exists( $demo['xml_file'] ) ) {
        echo 'Ready to import!';
    }
}

When you’ll use this:

  • Episode 7: Import functionality
  • Episode 8: Demo details page
  • Anywhere you need single demo info

Part 9: Complete Demo Library Code

All Functions Together

Here’s everything for the demo library:

/**
 * ========================================
 * DEMO LIBRARY FUNCTIONS
 * ========================================
 */

/**
 * Get available demos
 */
function versana_companion_get_available_demos() {
    $demos = array(
        'business' => array(
            'name'        => __( 'Business Website', 'versana-companion' ),
            'description' => __( 'Professional business website with services and portfolio sections. Perfect for corporate sites.', 'versana-companion' ),
            'preview_url' => 'https://demos.codoplex.com/versana/business/',
            'thumbnail'   => VERSANA_COMPANION_URL . 'assets/images/demos/business.jpg',
            'xml_file'    => VERSANA_COMPANION_PATH . 'demos/business/content.xml',
            'category'    => 'business',
            'tags'        => array( 'business', 'corporate' ),
        ),
        'blog' => array(
            'name'        => __( 'Personal Blog', 'versana-companion' ),
            'description' => __( 'Clean and minimal blog layout perfect for writers and content creators.', 'versana-companion' ),
            'preview_url' => 'https://demos.codoplex.com/versana/blog/',
            'thumbnail'   => VERSANA_COMPANION_URL . 'assets/images/demos/blog.jpg',
            'xml_file'    => VERSANA_COMPANION_PATH . 'demos/blog/content.xml',
            'category'    => 'blog',
            'tags'        => array( 'blog', 'minimal' ),
        ),
        'portfolio' => array(
            'name'        => __( 'Creative Portfolio', 'versana-companion' ),
            'description' => __( 'Showcase your work with a beautiful portfolio layout.', 'versana-companion' ),
            'preview_url' => 'https://demos.codoplex.com/versana/portfolio/',
            'thumbnail'   => VERSANA_COMPANION_URL . 'assets/images/demos/portfolio.jpg',
            'xml_file'    => VERSANA_COMPANION_PATH . 'demos/portfolio/content.xml',
            'category'    => 'portfolio',
            'tags'        => array( 'portfolio', 'creative' ),
        ),
    );
    
    return apply_filters( 'versana_companion_available_demos', $demos );
}

/**
 * Get single demo
 */
function versana_companion_get_demo( $demo_key ) {
    $demos = versana_companion_get_available_demos();
    return isset( $demos[ $demo_key ] ) ? $demos[ $demo_key ] : null;
}

/**
 * Add demo tabs
 */
function versana_companion_add_settings_tabs( $tabs ) {
    $tabs['demo_import'] = array(
        'title'    => __( 'Demo Import', 'versana-companion' ),
        'icon'     => 'dashicons-download',
        'callback' => 'versana_companion_render_demo_import_tab',
        'priority' => 5,
    );
    
    $tabs['companion'] = array(
        'title'    => __( 'Companion', 'versana-companion' ),
        'icon'     => 'dashicons-admin-plugins',
        'callback' => 'versana_companion_render_settings_tab',
        'priority' => 10,
    );
    
    return $tabs;
}
add_filter( 'versana_option_tabs', 'versana_companion_add_settings_tabs' );

/**
 * Render demo import tab
 */
function versana_companion_render_demo_import_tab() {
    if ( ! versana_companion_get_setting( 'enable_demo_import', true ) ) {
        ?>
        <div class="versana-tab-content">
            <div class="notice notice-warning">
                <p><?php esc_html_e( 'Demo import is disabled. Enable in Companion tab.', 'versana-companion' ); ?></p>
            </div>
        </div>
        <?php
        return;
    }
    
    $demos = versana_companion_get_available_demos();
    ?>
    <div class="versana-tab-content">
        <h2><?php esc_html_e( 'Import Demo Content', 'versana-companion' ); ?></h2>
        <p class="description">
            <?php esc_html_e( 'Choose a demo to import. This will add sample posts and pages.', 'versana-companion' ); ?>
        </p>
        
        <div class="versana-demo-library">
            <?php foreach ( $demos as $demo_key => $demo ) : ?>
                <div class="versana-demo-item">
                    <div class="demo-thumbnail">
                        <?php if ( ! empty( $demo['thumbnail'] ) && file_exists( str_replace( VERSANA_COMPANION_URL, VERSANA_COMPANION_PATH, $demo['thumbnail'] ) ) ) : ?>
                            <img src="<?php echo esc_url( $demo['thumbnail'] ); ?>" alt="<?php echo esc_attr( $demo['name'] ); ?>">
                        <?php else : ?>
                            <div class="demo-thumbnail-placeholder">
                                <span class="dashicons dashicons-admin-appearance"></span>
                            </div>
                        <?php endif; ?>
                    </div>
                    
                    <div class="demo-info">
                        <h3 class="demo-name"><?php echo esc_html( $demo['name'] ); ?></h3>
                        <p class="demo-description"><?php echo esc_html( $demo['description'] ); ?></p>
                    </div>
                    
                    <div class="demo-actions">
                        <?php if ( ! empty( $demo['preview_url'] ) ) : ?>
                            <a href="<?php echo esc_url( $demo['preview_url'] ); ?>" class="button" target="_blank">
                                <span class="dashicons dashicons-visibility"></span>
                                <?php esc_html_e( 'Preview', 'versana-companion' ); ?>
                            </a>
                        <?php endif; ?>
                        
                        <?php if ( file_exists( $demo['xml_file'] ) ) : ?>
                            <button type="button" class="button button-primary versana-import-demo" data-demo="<?php echo esc_attr( $demo_key ); ?>">
                                <span class="dashicons dashicons-download"></span>
                                <?php esc_html_e( 'Import', 'versana-companion' ); ?>
                            </button>
                        <?php else : ?>
                            <button type="button" class="button" disabled>
                                <?php esc_html_e( 'File Missing', 'versana-companion' ); ?>
                            </button>
                        <?php endif; ?>
                    </div>
                </div>
            <?php endforeach; ?>
        </div>
    </div>
    <?php
}

/**
 * Enqueue assets
 */
function versana_companion_enqueue_demo_library_assets( $hook ) {
    if ( 'appearance_page_versana-options' !== $hook ) {
        return;
    }
    
    $active_tab = isset( $_GET['tab'] ) ? sanitize_text_field( $_GET['tab'] ) : '';
    if ( 'demo_import' !== $active_tab ) {
        return;
    }
    
    wp_enqueue_style(
        'versana-companion-demo-library',
        VERSANA_COMPANION_URL . 'assets/css/demo-library.css',
        array(),
        VERSANA_COMPANION_VERSION
    );
}
add_action( 'admin_enqueue_scripts', 'versana_companion_enqueue_demo_library_assets' );

Conclusion

Congratulations! You’ve created a beautiful WordPress plugin demo library that displays available demos without needing a database. Simple, clean, and efficient!

What We Accomplished

✅ Understanding when NOT to use databases ✅ Defining demos in PHP arrays ✅ Adding Demo Import tab (priority 5) ✅ Displaying demos in grid layout ✅ Creating demo cards with thumbnails ✅ Adding preview and import buttons ✅ Styling with CSS ✅ Handling missing files gracefully ✅ Creating helper functions ✅ Testing the complete library

What We Learned

Technical Skills:

  • PHP arrays for static data
  • Grid layout with CSS
  • WordPress filters for tabs
  • Conditional asset loading
  • File existence checking
  • Extensibility with filters
  • Helper function patterns

Best Practices:

  • Use arrays for static data
  • Check file existence before displaying
  • Provide fallbacks (placeholders)
  • Only load CSS where needed
  • Make data filterable
  • Create helper functions
  • Handle edge cases

Key Takeaways

For WordPress plugin demo library:

  1. Arrays > Database – For static, fixed data
  2. Check Files – Always verify before showing
  3. Provide Fallbacks – Placeholders for missing images
  4. Grid Layout – Professional demo display
  5. Load Conditionally – CSS only where needed
  6. Make Extensible – Filters for customization
  7. Simple is Better – Don’t over-engineer

Your Plugin Progress

✓ Episode 2: Basic plugin
✓ Episode 3: Theme check
✓ Episode 4: Settings integration
✓ Episode 5: Demo library ← YOU ARE HERE
→ Episode 6: File operations (XML reading)
→ Episode 7: Demo import (actual import)

Frequently Asked Questions

Q: Why not use a database table? A: Demos are fixed, developer-defined content. Arrays are simpler, faster, and easier to maintain for static data.

Q: Can I add more demos later? A: Yes! Just add more items to the array in versana_companion_get_available_demos().

Q: What if I want to track downloads? A: You could add a simple counter in wp_options. No need for full table.

Q: Can child themes add demos? A: Yes! Use the versana_companion_available_demos filter to add custom demos.

Q: What thumbnail size should I use? A: 1200×800 pixels works well. CSS will resize automatically.

Q: Can I change the grid columns? A: Yes! Edit the CSS grid-template-columns property.

Q: What if XML file is missing? A: Button shows “File Missing” and is disabled. Code checks with file_exists().

Q: Can I add categories/tags? A: They’re in the array! We’ll use them for filtering in future episodes.


Next Episode Preview

Episode 6: File Operations

Now that we display demos, we’ll learn to read the XML files and prepare them for import!


Congratulations on completing Episode 5! You’ve built a professional demo library using simple arrays!


Series: Building Versana Companion Plugin

Episode: 5 of ongoing series (Demo Library Complete)

Leave a Reply

Search