Day: July 8, 2025

  • Building Custom Gutenberg Blocks: Elevate Your WordPress Editing Experience

    Building Custom Gutenberg Blocks: Elevate Your WordPress Editing Experience

    Gutenberg, the block editor introduced to WordPress in version 5.0, fundamentally transformed how users create and manage content. While the default set of blocks covers most needs, there comes a point in every developer’s journey where custom blocks are essential for delivering unique functionality and on-brand designs. In this article, I’ll walk you through the basics of building your own custom Gutenberg block and explain best practices to ensure maintainability and performance.

    Why Create Custom Blocks?

    Custom blocks empower you to:

    • Tailor editing experiences to content creators
    • Provide reusable design components
    • Encourage brand consistency
    • Extend functionality without shortcodes

    Setting Up Your Plugin

    To get started, you’ll want to create a new plugin. Begin by setting up your plugin directory (e.g., /wp-content/plugins/my-custom-blocks/) and placing a main PHP file inside:

    <?php
    /*
    Plugin Name: My Custom Blocks
    Description: Adds custom Gutenberg blocks.
    Version: 1.0
    Author: Presley
    */
    

    Next, use register_block_type to register your block. You will need two main files:

    • block.js (for block definition and React code)
    • style.css (for block styling)

    Example: A Simple Alert Box Block

    1. Enqueue Scripts in PHP:
    function mcb_register_block() {
        wp_register_script(
            'mcb-alert-block',
            plugins_url('block.js', __FILE__),
            array('wp-blocks', 'wp-element', 'wp-editor')
        );
        wp_register_style(
            'mcb-style',
            plugins_url('style.css', __FILE__)
        );
        register_block_type('mcb/alert-box', array(
            'editor_script' => 'mcb-alert-block',
            'style' => 'mcb-style',
        ));
    }
    add_action('init', 'mcb_register_block');
    
    1. Block JavaScript (block.js):
    const { registerBlockType } = wp.blocks;
    const { RichText } = wp.blockEditor;
    
    registerBlockType('mcb/alert-box', {
        title: 'Alert Box',
        icon: 'warning',
        category: 'widgets',
        attributes: {
            message: { type: 'string', source: 'html', selector: 'div' }
        },
        edit({ attributes, setAttributes }) {
            return (
                <RichText
                    tagName="div"
                    className="mcb-alert-box"
                    value={attributes.message}
                    onChange={(message) => setAttributes({ message })}
                    placeholder="Type your message..."
                />
            );
        },
        save({ attributes }) {
            return <div className="mcb-alert-box">{attributes.message}</div>;
        }
    });
    
    1. Styling (style.css):
    .mcb-alert-box {
      background: #fff3cd;
      border: 1px solid #ffeeba;
      padding: 16px;
      border-radius: 4px;
      color: #856404;
    }
    

    Best Practices for Custom Blocks

    • Namespace your block names and CSS classes to avoid conflicts.
    • Follow WordPress coding standards in PHP and JavaScript.
    • Document your code for the benefit of other developers.
    • Test across different themes and environments to ensure compatibility.
    • Consider localization/internationalization via wp.i18n functions.

    Final Thoughts

    Custom Gutenberg blocks are a powerful way to enhance the WordPress editing experience for developers, designers, and content creators alike. Once you have the basics down, experiment with Inspector Controls, custom attributes, and server-side rendering to create sophisticated, flexible blocks.

    Have you built any unique blocks? Share your experiences and questions in the comments below!

    — Presley

  • Securing Your WordPress Site: Essential Practices for Modern Sites

    Securing Your WordPress Site: Essential Practices for Modern Sites

    As a web developer who has seen countless WordPress installs over the past decade, I can tell you that site security remains one of the most crucial and yet sometimes overlooked aspects of WordPress management. Whether you’re building a personal blog, an e-commerce platform, or a network of sites, a proactive approach to security goes hand-in-hand with performance, reliability, and user trust.

    In this article, I’ll walk you through actionable strategies to lock down your WordPress sites and help you avoid common pitfalls that could leave your site vulnerable.

    1. Keep WordPress Core, Themes, and Plugins Updated

    This is your first line of defense. Outdated core files, themes, and plugins are the most commonly exploited vulnerabilities. Enable auto-updates when possible, but always test updates in a staging environment if you’re running mission-critical or custom sites. Remove unused plugins and themes entirely—deactivated code can still be a threat.

    2. Enforce Strong Authentication

    Default usernames like “admin” and weak passwords are invitations for brute-force attacks. Choose complex passwords and enable two-factor authentication (2FA) for all user accounts. Popular plugins such as Wordfence and iThemes Security make enabling 2FA straightforward.

    3. Restrict Access and Permissions

    Apply the Principle of Least Privilege: only give users the permissions they need. For multisite networks, be especially careful with Super Admin access. Use dedicated admin accounts for site management, and encourage content creators to use Contributor or Author roles.

    4. Secure wp-config.php and Sensitive Files

    Move wp-config.php one directory above the root, and add rules to your .htaccess file to prevent direct access to sensitive files such as wp-config.php and .htaccess itself. For example:

    <files wp-config.php>
      order allow,deny
      deny from all
    </files>
    

    5. Install a Web Application Firewall (WAF)

    A WAF can block common threats like SQL injection, XSS, and unauthorized access attempts. Many reputable security plugins offer WAF features, or you can use a cloud-based proxy WAF for enhanced protection.

    6. Regular Backups and Monitoring

    No security setup is perfect. Schedule automatic backups and ensure you can restore your site quickly in case of compromise. Monitor your site’s logs for suspicious activity—plugins like WP Activity Log provide granular insights.

    7. Disable XML-RPC If Not Needed

    XML-RPC is an old protocol that can be exploited for DDoS or brute-force attacks. If you’re not using it for remote publishing or third-party apps, disable it:

    add_filter('xmlrpc_enabled', '__return_false');
    

    Final Thoughts

    Security is an ongoing process—not a set-and-forget task. By implementing these foundational practices, you’ll significantly reduce your attack surface and gain peace of mind knowing your WordPress sites are better protected.

    Have more questions about hardening your WordPress setup? Drop them in the comments below or reach out on Twitter. For more in-depth WordPress tutorials and development tips, be sure to check out my previous articles!

    — Presley

  • Managing Environment Variables in FastAPI Applications

    Managing Environment Variables in FastAPI Applications

    As a backend developer, one of the foundational best practices is to keep sensitive information such as API keys, database credentials, and configuration settings out of your codebase. Instead, we use environment variables. In this article, I’ll walk you through practical techniques for managing environment variables effectively in your FastAPI projects.

    Why Use Environment Variables?

    Environment variables provide a secure and flexible way to configure your application from outside the code. Storing secrets in version-controlled Python files risks accidental exposure and makes changing configurations across environments (development, staging, production) cumbersome.

    Loading Environment Variables

    Let’s consider a typical FastAPI setup. The two common approaches for loading environment variables are:

    1. The Standard Library (os.environ)
    2. Third-party Packages (python-dotenv, pydantic settings)

    Using python-dotenv for Local Development

    The python-dotenv package lets you define a .env file in your project root:

    DATABASE_URL=postgresql://user:pass@localhost/db
    SECRET_KEY=supersecretkey
    

    Then, load these variables at startup:

    from dotenv import load_dotenv
    import os
    
    load_dotenv()  # Loads variables from .env into the environment
    
    DATABASE_URL = os.getenv("DATABASE_URL")
    SECRET_KEY = os.getenv("SECRET_KEY")
    

    Using Pydantic Settings Management

    Pydantic (FastAPI’s favorite data validation library) provides a clean way to centralize app configuration:

    from pydantic import BaseSettings
    
    class Settings(BaseSettings):
        database_url: str
        secret_key: str
    
        class Config:
            env_file = ".env"
    
    settings = Settings()
    

    You can then import settings wherever you need configuration values. This method also validates the types of your environment variables and falls back to system os.environ if needed.

    Injecting Settings into FastAPI Dependencies

    A tidy way to use settings in your app is via dependency injection:

    from fastapi import Depends, FastAPI
    
    app = FastAPI()
    
    def get_settings():
        return settings
    
    @app.get("/info")
    def read_info(settings: Settings = Depends(get_settings)):
        return {"db": settings.database_url}
    

    This technique brings testability and configurability to your endpoints.

    Summary Tips

    • Never commit your .env file if it contains secrets. Add it to .gitignore.
    • Leverage Pydantic settings for type safety and validation.
    • Use dependency injection to make config available wherever you need it.

    Managing environment variables well sets the foundation for robust, secure FastAPI services—whether you’re running locally or deploying to production.

    Happy coding!

    — Fast Eddy

  • Managing Shell History in Unix: Bash and Beyond

    Managing Shell History in Unix: Bash and Beyond

    On Linux servers, the command line is king—and as you work in a Unix environment, your command history becomes an invaluable asset. Yet, many sysadmins and developers aren’t aware of the subtle (and not-so-subtle) differences in how shells like Bash, Zsh, and others manage their history files. This article explores how history management works across common shell environments, with a focus on Bash, and offers tips for boosting security and efficiency on your server.

    Bash: The Most Common Shell

    The Bourne Again SHell (Bash) is the default shell for many Linux distributions. Its history management is robust and highly configurable:

    • History File: Bash stores your command history in ~/.bash_history, though this can be customized by setting the $HISTFILE variable.
    • Session and File: Commands are kept in RAM until you exit the shell; then, they are written to the history file. You can force an update with the history -a and history -w commands.
    • Concurrency: Before Bash 5, concurrent (simultaneous) sessions could overwrite history. Modern versions support the histappend option (shopt -s histappend) and the PROMPT_COMMAND="history -a; history -n" trick to avoid losing commands between sessions.
    • Configuration: Variables like HISTSIZE (in-memory size) and HISTFILESIZE (on disk) define limits. Sensitive data can be excluded with the HISTIGNORE and HISTCONTROL variables.

    Zsh: Feature-Rich History

    Zsh has a more advanced history system, and it’s become popular for its customization:

    • Default File: Zsh saves history in ~/.zsh_history.
    • Incremental Updates: Zsh writes each command immediately (with the INC_APPEND_HISTORY option), preventing loss between sessions.
    • Shared History: Use setopt SHARE_HISTORY to synchronize history across all running sessions in real time.

    Other Shells: sh, ksh, fish

    • sh/dash: Basic Bourne dashboards (like /bin/sh or dash) typically lack user-specific history.
    • ksh (KornShell): Similar to Bash, but with different default paths (e.g., ~/.sh_history).
    • fish: The Friendly Interactive Shell stores history in a human-readable YAML file (~/.local/share/fish/fish_history), auto-updating as you go.

    Tips for Effective History Management

    1. Don’t Log Sensitive Data: Set HISTCONTROL=ignorespace and start sensitive commands with a space, or configure HISTIGNORE to skip certain patterns (like *password*).
    2. Increase Size Limits: Bump up HISTSIZE and HISTFILESIZE for longer recall.
    3. Clear or Edit History: Use history -d <line_number> (Bash) to delete problematic entries, or simply edit the history file.
    4. Search Efficiently: Press Ctrl+R for reverse search, or use grep on your .bash_history for deeper dives.

    Conclusion

    Different shells have different philosophies and defaults for history management, and understanding these subtleties is key for both productivity and security. Whether you’re tailoring .bashrc or .zshrc, a little configuration goes a long way. Master your shell history, and you’ll become a more effective sysadmin or developer—one command at a time.