• Skip to secondary menu
  • Skip to main content
  • Skip to primary sidebar
  • Home
  • Projects
  • Products
  • Themes
  • Tools
  • Request for Quote

Vengala Vinay

Having 12+ Years of Experience in Software Development

  • Home
  • WordPress
  • PHP
    • Codeigniter
  • Django
  • Magento
  • Selenium
  • Server
Home » Step-by-Step Guide to building a custom database optimizer portal block for Gutenberg using SolidJS high-performance reactive components

Step-by-Step Guide to building a custom database optimizer portal block for Gutenberg using SolidJS high-performance reactive components

Setting Up the Development Environment

To build a custom Gutenberg block leveraging SolidJS for a database optimizer portal, we need a robust development environment. This involves setting up a local WordPress instance, Node.js with npm/yarn, and a build toolchain capable of compiling SolidJS components into a format WordPress can consume.

We’ll use WP-CLI for managing our WordPress installation and a modern JavaScript build tool like Vite for its speed and efficiency in handling SolidJS compilation and asset bundling.

Local WordPress Installation with WP-CLI

Ensure you have WP-CLI installed. If not, follow the official installation guide. Then, create a new WordPress site:

wp core download
wp config create --dbname=wp_db --dbuser=wp_user --dbpass=wp_password --dbhost=localhost
wp core install --url=http://localhost:8888 --title="DB Optimizer Portal" --admin_user=admin --admin_password=password [email protected]
wp plugin install wordpress-seo --activate
wp theme install twentytwentyone --activate

This command sequence downloads WordPress, configures the database, performs a core installation, and installs/activates essential plugins and themes. Adjust database credentials and URLs as per your local setup.

Node.js and Project Initialization

Verify your Node.js installation:

node -v
npm -v

Create a new directory for your Gutenberg block plugin and initialize a Node.js project:

mkdir wp-db-optimizer-block
cd wp-db-optimizer-block
npm init -y

Vite Configuration for SolidJS and WordPress

We’ll use Vite as our build tool. Install the necessary dependencies:

npm install --save-dev vite @vitejs/plugin-react @vitejs/plugin-react-swc solid-refresh vite-plugin-solid

Create a vite.config.js file in the root of your plugin directory:

import { defineConfig } from 'vite';
import solidPlugin from 'vite-plugin-solid';
import react from '@vitejs/plugin-react'; // Although we use Solid, some WP dependencies might expect React

export default defineConfig(({ command }) => ({
  plugins: [
    solidPlugin(),
    react(), // Include for compatibility if needed
  ],
  build: {
    outDir: 'build', // Output directory for compiled assets
    emptyOutDir: true,
    rollupOptions: {
      input: {
        index: 'src/index.js', // Entry point for your SolidJS app
      },
      output: {
        entryFileNames: '[name].js',
        chunkFileNames: '[name]-[hash].js',
        assetFileNames: '[name]-[hash].[ext]',
      },
    },
  },
  server: {
    // Configure development server if needed, though WordPress handles this
    // For direct asset serving during development, this might be useful
  },
}));

Create a src directory and an index.js file within it. This will be the entry point for your SolidJS application.

// src/index.js
import { render } from 'solid-js/web';
import App from './App';

document.addEventListener('DOMContentLoaded', () => {
  const elements = document.querySelectorAll('.wp-block-your-plugin-db-optimizer');
  elements.forEach(element => {
    render(() => , element);
  });
});

Now, create a basic src/App.jsx file:

// src/App.jsx
import { createSignal } from 'solid-js';

function App() {
  const [count, setCount] = createSignal(0);

  return (
    <div>
      <h2>Database Optimizer Component</h2>
      <p>This is a SolidJS component within Gutenberg.</p>
      <button onClick={() => setCount(count() + 1)}>
        Clicked {count()} times
      </button>
    </div>
  );
}

export default App;

Developing the Gutenberg Block Plugin

We’ll structure our plugin to register a server-side block and enqueue our compiled SolidJS assets.

Plugin Structure and Registration

Create the main plugin file, e.g., wp-db-optimizer-block.php:

<?php
/**
 * Plugin Name: DB Optimizer Block
 * Description: A custom Gutenberg block for database optimization insights using SolidJS.
 * Version: 1.0.0
 * Author: Your Name
 * License: GPL-2.0-or-later
 * Text Domain: db-optimizer-block
 */

if ( ! defined( 'ABSPATH' ) ) {
    exit; // Exit if accessed directly.
}

/**
 * Registers the block using the metadata loaded from the `block.json` file.
 * Behind the scenes, it registers also all assets so they can be enqueued
 * through the block editor in the corresponding context.
 *
 * @see https://developer.wordpress.org/reference/functions/register_block_type/
 */
function db_optimizer_block_init() {
    register_block_type( __DIR__ . '/build' );
}
add_action( 'init', 'db_optimizer_block_init' );
?>

Next, create a block.json file in the root of your plugin directory. This file describes the block to Gutenberg and specifies asset dependencies.

{
    "$schema": "https://schemas.wp.org/trunk/block.json",
    "apiVersion": 3,
    "name": "your-plugin/db-optimizer",
    "version": "0.1.0",
    "title": "DB Optimizer Portal",
    "category": "widgets",
    "icon": "chart-bar",
    "description": "Displays database optimization insights.",
    "attributes": {
        "message": {
            "type": "string",
            "default": "Welcome to the DB Optimizer!"
        }
    },
    "editorScript": "file:./build/index.js",
    "editorStyle": "file:./build/style-index.css",
    "style": "file:./build/style-index.css",
    "render": "file:./render.php"
}

The render property points to a render.php file, which will handle server-side rendering. Create this file:

<?php
/**
 * Server-side rendering for the DB Optimizer block.
 *
 * @package db-optimizer-block
 */

if ( ! defined( 'ABSPATH' ) ) {
    exit; // Exit if accessed directly.
}

/**
 * Renders the DB Optimizer block on the server.
 *
 * @param array $attributes The block attributes.
 * @return string Rendered block output.
 */
function render_db_optimizer_block( $attributes ) {
    // The SolidJS app will mount onto this div.
    // We can pass data via data attributes if needed.
    $message = isset( $attributes['message'] ) ? esc_html( $attributes['message'] ) : 'Default Message';

    // Enqueue the compiled SolidJS assets.
    // Vite's output names are hashed, so we need to find the correct files.
    // A more robust solution would involve a manifest file.
    $asset_path = plugin_dir_path( __FILE__ ) . 'build/';
    $asset_url = plugin_dir_url( __FILE__ ) . 'build/';

    $js_file = glob( $asset_path . 'index-*.js' );
    $css_file = glob( $asset_path . 'style-index-*.css' ); // Assuming style-index.css is also processed

    if ( empty( $js_file ) || empty( $css_file ) ) {
        return '<p>Error: Compiled assets not found. Please run `npm run build`.</p>';
    }

    $js_file_name = basename( $js_file[0] );
    $css_file_name = basename( $css_file[0] );

    wp_enqueue_script( 'db-optimizer-block-solid', $asset_url . $js_file_name, array(), '1.0.0', true );
    wp_enqueue_style( 'db-optimizer-block-style', $asset_url . $css_file_name, array(), '1.0.0' );

    // The SolidJS app will mount onto this div.
    // The class name should match the one used in src/index.js.
    // We can pass initial data via data attributes.
    return sprintf(
        '<div class="wp-block-your-plugin-db-optimizer" data-initial-message="%s">%s</div>',
        esc_attr( $message ),
        '' // The SolidJS app will render its content here.
    );
}

// The block.json specifies 'render' as a file path.
// WordPress automatically calls register_block_type with the 'render_callback'
// option set to the content of the specified file if it's a PHP file.
// So, we don't need to explicitly hook `render_db_optimizer_block`.
// However, if we wanted to pass attributes to the render function, we'd do:
// register_block_type( __DIR__ . '/build', array( 'render_callback' => 'render_db_optimizer_block' ) );
// For simplicity with file-based render, WordPress handles it.
// The `render.php` file itself is executed.
// We need to ensure the enqueue calls happen correctly.
// A better approach is to use `enqueue_block_assets` or `enqueue_block_editor_assets`.

// Let's refine the asset enqueuing to be more robust.
// We'll use a manifest file generated by Vite for accurate asset paths.
// For now, we'll stick to globbing, but acknowledge its fragility.

// The `register_block_type` call in `db_optimizer_block_init` with `__DIR__ . '/build'`
// will automatically look for `block.json` and use its `render` property.
// If `render` is a PHP file, that file's content is treated as the render callback.
// Therefore, the `render.php` file *is* the callback.
// We need to ensure assets are enqueued correctly.

// A more standard approach for asset enqueuing with `register_block_type`
// is to define them in `block.json` under `editorScript`, `editorStyle`, `style`.
// The `render` property is for the server-side HTML output.
// The SolidJS app will mount on the DOM element generated by `render.php`.
// The `editorScript` and `style` in `block.json` will handle editor-time loading.
// For front-end loading, we need to ensure the assets are enqueued.

// Let's adjust `block.json` and `render.php` for better asset management.
// The `render.php` should ideally *not* enqueue assets directly.
// Instead, `block.json` should define `script` and `style` for front-end.

// Revised block.json (add these for front-end assets):
// "script": "file:./build/index.js",
// "style": "file:./build/style-index.css",

// With these added, WordPress will automatically enqueue them for the front-end
// when the block is rendered. The `render.php` will just output the HTML container.

// Let's assume `block.json` has been updated with `script` and `style` for front-end.
// The `render.php` content then becomes simpler:
?>
<!-- wp:paragraph -->
<p>Loading Database Optimizer...</p>
<!-- /wp:paragraph -->
<div class="wp-block-your-plugin-db-optimizer" data-initial-message="<?php echo esc_attr( $attributes['message'] ?? 'Default Message' ); ?>"></div>
<?php
// The above HTML will be the output. The SolidJS app will mount onto the div.
// The `block.json` will handle asset enqueuing for both editor and front-end.
// The `editorScript` and `editorStyle` are for the block editor.
// The `script` and `style` (if added) are for the front-end.
// If `script` and `style` are not in `block.json`, we'd need a hook like `wp_enqueue_scripts`.
// For this example, let's assume `block.json` is updated to include front-end assets.
?>

Update your block.json to include front-end asset definitions:

{
    "$schema": "https://schemas.wp.org/trunk/block.json",
    "apiVersion": 3,
    "name": "your-plugin/db-optimizer",
    "version": "0.1.0",
    "title": "DB Optimizer Portal",
    "category": "widgets",
    "icon": "chart-bar",
    "description": "Displays database optimization insights.",
    "attributes": {
        "message": {
            "type": "string",
            "default": "Welcome to the DB Optimizer!"
        }
    },
    "editorScript": "file:./build/index.js",
    "editorStyle": "file:./build/style-index.css",
    "style": "file:./build/style-index.css",
    "script": "file:./build/index.js",
    "render": "file:./render.php"
}

Now, the render.php can be simplified to just output the HTML container:

<?php
/**
 * Server-side rendering for the DB Optimizer block.
 *
 * @package db-optimizer-block
 */

if ( ! defined( 'ABSPATH' ) ) {
    exit; // Exit if accessed directly.
}

// The block.json handles asset enqueuing for both editor and front-end.
// This file just needs to output the HTML structure.
$message = $attributes['message'] ?? 'Default Message';
?>
<div class="wp-block-your-plugin-db-optimizer" data-initial-message="<?php echo esc_attr( $message ); ?>"></div>

Building and Integrating SolidJS Components

With the basic WordPress plugin structure in place, we can now focus on the SolidJS components that will power the database optimizer portal.

Creating the Main Application Component

Let’s enhance src/App.jsx to fetch and display some hypothetical database optimization data. For this example, we’ll simulate an API call.

// src/App.jsx
import { createSignal, createEffect, Show } from 'solid-js';
import { styled } from 'solid-styled-components'; // Example of using styled-components

// Mock API function
const fetchDbOptimizations = async () => {
  // In a real application, this would be an AJAX call to your WordPress REST API
  // or a custom endpoint.
  await new Promise(resolve => setTimeout(resolve, 1000)); // Simulate network delay
  return {
    tables: [
      { name: 'wp_posts', size: '10MB', rows: 15000, needs_optimization: true },
      { name: 'wp_options', size: '2MB', rows: 5000, needs_optimization: false },
      { name: 'wp_users', size: '1MB', rows: 1200, needs_optimization: true },
    ],
    total_size: '13MB',
    recommendations: [
      'Optimize wp_posts table by removing old revisions.',
      'Consider indexing frequently queried columns in wp_options.',
    ],
  };
};

const Container = styled.div`
  padding: 20px;
  border: 1px solid #ccc;
  border-radius: 5px;
  background-color: #f9f9f9;
  font-family: sans-serif;
`;

const Title = styled.h2`
  color: #333;
  margin-bottom: 15px;
`;

const Table = styled.table`
  width: 100%;
  border-collapse: collapse;
  margin-bottom: 20px;

  th, td {
    border: 1px solid #ddd;
    padding: 8px;
    text-align: left;
  }

  th {
    background-color: #e9e9e9;
  }
`;

const Highlight = styled.span`
  color: red;
  font-weight: bold;
`;

function App() {
  const [data, setData] = createSignal(null);
  const [loading, setLoading] = createSignal(true);
  const [error, setError] = createSignal(null);

  // Get initial message from data attribute
  const initialMessage = document.currentScript.closest('.wp-block-your-plugin-db-optimizer')?.dataset?.initialMessage || 'Database Optimizer';

  createEffect(() => {
    fetchDbOptimizations()
      .then(result => {
        setData(result);
        setLoading(false);
      })
      .catch(err => {
        setError('Failed to load optimization data.');
        console.error(err);
        setLoading(false);
      });
  });

  return (
    <Container>
      <Title>{initialMessage}</Title>

      <Show when={loading()}>
        <p>Loading optimization data...</p>
      </Show>

      <Show when={error()}>
        <p style="color: red;">{error()}</p>
      </Show>

      <Show when={!loading() && data()}>
        <p>Total Database Size: <strong>{data().total_size}</strong></p>

        <h3>Table Status:</h3>
        <Table>
          <thead>
            <tr>
              <th>Table Name</th>
              <th>Size</th>
              <th>Rows</th>
              <th>Needs Optimization</th>
            </tr>
          </thead>
          <tbody>
            <For each={data().tables} fallback={<tr><td colspan="4">No table data available.</td></tr>}>
              {(table) => (
                <tr>
                  <td>{table.name}</td>
                  <td>{table.size}</td>
                  <td>{table.rows}</td>
                  <td>
                    <Show when={table.needs_optimization}>
                      <Highlight>Yes</Highlight>
                    </Show>
                    <Show when={!table.needs_optimization}>
                      No
                    </Show>
                  </td>
                </tr>
              )}
            </For>
          </tbody>
        </Table>

        <h3>Recommendations:</h3>
        <ul>
          <For each={data().recommendations} fallback={<li>No recommendations available.</li>}>
            {(recommendation) => (
              <li>{recommendation}</li>
            )}
          </For>
        </ul>
      </Show>
    </Container>
  );
}

export default App;

To use styled-components with SolidJS, you’ll need to install the relevant package:

npm install solid-styled-components

The src/index.js needs to be updated to correctly find the mounting element and potentially pass data from attributes.

// src/index.js
import { render } from 'solid-js/web';
import App from './App';

document.addEventListener('DOMContentLoaded', () => {
  const elements = document.querySelectorAll('.wp-block-your-plugin-db-optimizer');
  elements.forEach(element => {
    // Pass data from the data attribute to the SolidJS app
    const initialMessage = element.dataset.initialMessage || 'Database Optimizer';
    render(() => <App initialMessage={initialMessage} />, element);
  });
});

And update src/App.jsx to accept and use the initialMessage prop:

// src/App.jsx
import { createSignal, createEffect, Show, For } from 'solid-js';
import { styled } from 'solid-styled-components';

// ... (fetchDbOptimizations and styled components remain the same) ...

function App(props) { // Accept props
  const [data, setData] = createSignal(null);
  const [loading, setLoading] = createSignal(true);
  const [error, setError] = createSignal(null);

  createEffect(() => {
    fetchDbOptimizations()
      .then(result => {
        setData(result);
        setLoading(false);
      })
      .catch(err => {
        setError('Failed to load optimization data.');
        console.error(err);
        setLoading(false);
      });
  });

  return (
    <Container>
      <Title>{props.initialMessage}</Title> {/* Use the prop */}

      <Show when={loading()}>
        <p>Loading optimization data...</p>
      </Show>

      <Show when={error()}>
        <p style="color: red;">{error()}</p>
      </Show>

      <Show when={!loading() && data()}>
        <p>Total Database Size: <strong>{data().total_size}</strong></p>

        <h3>Table Status:</h3>
        <Table>
          <thead>
            <tr>
              <th>Table Name</th>
              <th>Size</th>
              <th>Rows</th>
              <th>Needs Optimization</th>
            </tr>
          </thead>
          <tbody>
            <For each={data().tables} fallback={<tr><td colspan="4">No table data available.</td></tr>}>
              {(table) => (
                <tr>
                  <td>{table.name}</td>
                  <td>{table.size}</td>
                  <td>{table.rows}</td>
                  <td>
                    <Show when={table.needs_optimization}>
                      <Highlight>Yes</Highlight>
                    </Show>
                    <Show when={!table.needs_optimization}>
                      No
                    </Show>
                  </td>
                </tr>
              )}
            </For>
          </tbody>
        </Table>

        <h3>Recommendations:</h3>
        <ul>
          <For each={data().recommendations} fallback={<li>No recommendations available.</li>}>
            {(recommendation) => (
              <li>{recommendation}</li>
            )}
          </For>
        </ul>
      </Show>
    </Container>
  );
}

export default App;

Building Assets

Add build scripts to your package.json:

{
  "name": "wp-db-optimizer-block",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "dev": "vite",
    "build": "vite build",
    "preview": "vite preview"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "@vitejs/plugin-react": "^4.2.1",
    "react": "^18.2.0",
    "react-dom": "^18.2.0",
    "solid-js": "^1.8.15",
    "solid-refresh": "^0.2.0",
    "vite": "^5.1.4",
    "vite-plugin-solid": "^2.10.1",
    "vite-plugin-react-swc": "^3.3.2",
    "solid-styled-components": "^0.1.1"
  },
  "dependencies": {
    "solid-styled-components": "^0.1.1"
  }
}

Run the build command:

npm run build

This will compile your SolidJS code and place the output (e.g., index.js, style-index.css, and their hashed versions) into the build directory. WordPress will then enqueue these assets based on the block.json configuration.

Testing and Deployment

After building the assets, activate your plugin in the WordPress admin area. You should now be able to add the “DB Optimizer Portal” block to your posts or pages. The SolidJS component will render, fetch mock data, and display the optimization insights.

Editor Experience

In the Gutenberg editor, the editorScript and editorStyle defined in block.json will load. Your SolidJS component will render within the editor canvas, providing a live preview. You can also use the block inspector controls to modify attributes like the message.

Front-end Rendering

On the front-end of your website, the script and style defined in block.json will be enqueued. The render.php file will output the initial HTML container, and your SolidJS application will mount onto it, displaying the data dynamically.

Deployment Considerations

For production deployment:

  • Ensure your build process is integrated into your CI/CD pipeline.
  • The build directory containing the compiled assets should be committed to your repository or generated during the build process.
  • The WordPress plugin files, including the build directory, should be deployed to your web server.
  • Consider using a WordPress plugin for managing asset manifests generated by Vite to handle cache busting more reliably than globbing.

This setup provides a high-performance, reactive user interface for your database optimization portal directly within the WordPress ecosystem, leveraging the power of SolidJS for efficient rendering and state management.

Primary Sidebar

A little about the Author

Having 12+ Years of Experience in Software Development, Vinay is a principal software architect, senior systems engineer, and elite technical consultant. He specializes in bespoke PHP/WordPress development, high-performance Magento 2 & Shopify architectures, custom plugin/theme development from scratch, and legacy code modernization (including VB6, VB.NET, PyQt, and Crystal Reports). Known for solving complex database bottlenecks, speed optimization (Core Web Vitals), and advanced security code auditing, Vinay engineers production-ready systems designed to scale under heavy concurrent load conditions.



Chat on WhatsApp

Recent Posts

  • Leveraging PHP 8 JIT and AWS Lambda for High-Performance, Serverless WordPress REST API Backends
  • Beyond the Basics: Leveraging PHP 8.3’s JIT Compiler and Fibers for High-Concurrency Laravel Applications
  • Zero-Downtime Deployments with Docker, Laravel, and AWS ECS: A Deep Dive into Blue/Green Strategies
  • Leveraging PHP 9’s JIT and Concurrency Features for High-Performance Laravel Microservices on AWS ECS
  • Leveraging PHP 8.3 JIT and OPcache for Sub-Millisecond API Response Times: A Practical Deep Dive

Categories

  • apache (1)
  • Business & Monetization (390)
  • Centos (4)
  • Comparisons & Decision Making (55)
  • Debian (2)
  • Debugging & Troubleshooting (664)
  • Desktop Applications (14)
  • DevOps (11)
  • DevOps & Cloud Scaling (962)
  • Django (1)
  • Laravel (6)
  • Migration & Architecture (192)
  • Mobile Applications (24)
  • MySQL (1)
  • Performance & Optimization (873)
  • PHP (14)
  • PHP Development (49)
  • Plugins & Themes (244)
  • Programming Languages (10)
  • Python (20)
  • Ruby on Rails (1)
  • Security & Compliance (650)
  • SEO & Growth (492)
  • Server (118)
  • Softwares (1)
  • Ubuntu (9)
  • Uncategorized (17)
  • VB6 & VB.NET (8)
  • Web Applications & Frontend (19)
  • Web Assembly (Wasm) (2)
  • WordPress (24)
  • WordPress Plugin Development (728)
  • WordPress Theme Development (357)

Recent Posts

  • Leveraging PHP 8 JIT and AWS Lambda for High-Performance, Serverless WordPress REST API Backends
  • Beyond the Basics: Leveraging PHP 8.3's JIT Compiler and Fibers for High-Concurrency Laravel Applications
  • Zero-Downtime Deployments with Docker, Laravel, and AWS ECS: A Deep Dive into Blue/Green Strategies

Top Categories

  • DevOps & Cloud Scaling (962)
  • Performance & Optimization (873)
  • WordPress Plugin Development (728)
  • Debugging & Troubleshooting (664)
  • Security & Compliance (650)
  • SEO & Growth (492)

Our Products

  • ERP & LMS Systems (4)
  • Directories & Marketplaces (4)
  • Healthcare Portals (3)
  • Point of Sale (POS) (2)
  • E-Commerce Engines (2)

Our Services

  • E-Commerce Development (10)
  • WordPress Development (8)
  • Python & Desktop GUI (7)
  • General Consulting (7)
  • Legacy Modernization (5)
  • Mobile App Development (4)

Copyright © 2026 · Vinay Vengala