Blog
Cómo construir un plugin sencillo para WordPress (desde la idea al repo)
Brayan Developer
••4 min de lectura

Cómo construir un plugin sencillo para WordPress desde la idea al repo Contenido 1) Define la idea y el alcance 2) Estructura mínima de un plugin 3) Código base funcional 4) README y assets del repositorio 5) Publicar en WordPress.org (SVN) o GitHub 6) Checklist de publicación FAQ 1) Define la idea y el alcance [...]
Cómo construir un plugin sencillo para WordPress desde la idea al repo#
Contenido
- 1) Define la idea y el alcance
- 2) Estructura mínima de un plugin
- 3) Código base funcional
- 4) README y assets del repositorio
- 5) Publicar en WordPress.org (SVN) o GitHub
- 6) Checklist de publicación
- FAQ
1) Define la idea y el alcance#
Elige un problema pequeño y útil: un shortcode, un ajuste en admin o una integración simple. Limita el alcance para lanzar rápido.
Objetivo: Añadir un shortcode con mensaje personalizable.
Usuario: Administrador/Editor
Acción principal: Insertar [mi_plugin mensaje="..."]
No incluye: Bloques complejos, API externas
Éxito: Shortcode visible y opción en Ajustes > Mi Plugin
2) Estructura mínima de un plugin#
mi-plugin/
├─ mi-plugin.php
├─ readme.txt
├─ includes/
│ ├─ class-mi-plugin.php
│ └─ functions.php
├─ assets/
│ ├─ frontend.css
│ └─ icon-256x256.png
└─ languages/
└─ mi-plugin-es_ES.mo
3) Código base funcional#
Copia estos fragmentos en tus archivos. Activa el plugin y prueba el shortcode [mi_plugin mensaje="¡Hola!"]Contenido.
Archivo principal: mi-plugin.php#
<?php
/**
* Plugin Name: Mi Plugin Sencillo
* Description: Ejemplo con shortcode y página de ajustes.
* Version: 1.0.0
* Author: Tu Nombre
* License: GPL-2.0-or-later
* Text Domain: mi-plugin
* Domain Path: /languages
*/
if ( ! defined( 'ABSPATH' ) ) exit;
define( 'MI_PLUGIN_VERSION', '1.0.0' );
define( 'MI_PLUGIN_PATH', plugin_dir_path(__FILE__) );
define( 'MI_PLUGIN_URL', plugin_dir_url(__FILE__) );
add_action('plugins_loaded', function(){
load_plugin_textdomain('mi-plugin', false, dirname(plugin_basename(__FILE__)).'/languages');
});
register_activation_hook(__FILE__, function(){ add_option('mi_plugin_opcion','on'); });
require_once MI_PLUGIN_PATH.'includes/functions.php';
require_once MI_PLUGIN_PATH.'includes/class-mi-plugin.php';
add_shortcode('mi_plugin','mi_plugin_shortcode');
add_action('admin_menu', function(){
add_options_page(__('Ajustes de Mi Plugin','mi-plugin'),'Mi Plugin','manage_options','mi-plugin-ajustes','mi_plugin_pantalla_ajustes');
});
add_action('wp_enqueue_scripts', function(){
wp_enqueue_style('mi-plugin-frontend', MI_PLUGIN_URL.'assets/frontend.css', [], MI_PLUGIN_VERSION);
});
Funciones: includes/functions.php#
<?php
if ( ! defined( 'ABSPATH' ) ) exit;
function mi_plugin_shortcode($atts = [], $content = '') {
$atts = shortcode_atts(['mensaje' => __('Hola desde Mi Plugin 👋','mi-plugin')], $atts, 'mi_plugin');
ob_start(); ?>
<div class="mi-plugin-box">
<strong><?php echo esc_html($atts['mensaje']); ?></strong>
<?php if ($content) : ?>
<div class="mi-plugin-content"><?php echo wp_kses_post($content); ?></div>
<?php endif; ?>
</div>
<?php return ob_get_clean();
}
function mi_plugin_pantalla_ajustes(){
if ( isset($_POST['mi_plugin_nonce']) && wp_verify_nonce($_POST['mi_plugin_nonce'],'mi_plugin_guardar') ) {
update_option('mi_plugin_opcion', sanitize_text_field($_POST['mi_plugin_opcion'] ?? 'off'));
echo '<div class="updated"><p>'.esc_html__('Ajustes guardados','mi-plugin').'</p></div>';
}
$valor = get_option('mi_plugin_opcion','on'); ?>
<div class="wrap">
<h1><?php esc_html_e('Ajustes de Mi Plugin','mi-plugin'); ?></h1>
<form method="post">
<?php wp_nonce_field('mi_plugin_guardar','mi_plugin_nonce'); ?>
<label>
<input type="checkbox" name="mi_plugin_opcion" value="on" <?php checked($valor,'on'); ?>>
<?php esc_html_e('Activar mensaje por defecto','mi-plugin'); ?>
</label>
<p><button class="button button-primary"><?php esc_html_e('Guardar cambios','mi-plugin'); ?></button></p>
</form>
</div>
<?php }
Clase (opcional): includes/class-mi-plugin.php#
<?php
if ( ! defined( 'ABSPATH' ) ) exit;
class MI_Plugin {
public function __construct(){ add_action('init', [$this,'boot']); }
public function boot(){
add_shortcode('mi_plugin_time', function(){
return '<span class="mi-plugin-time">'.esc_html(date_i18n(get_option('time_format'))).'</span>';
});
}
}
new MI_Plugin();
CSS mínimo: assets/frontend.css#
.mi-plugin-box{padding:12px;border:1px solid #e3e8ef;border-radius:10px;background:#f8fafc;font:500 16px/1.5 system-ui,-apple-system,Segoe UI,Roboto,Arial}
.mi-plugin-content{margin-top:6px;color:#334155}
4) README y assets del repositorio#
Crea readme.txt y los banners para WordPress.org.
=== Mi Plugin Sencillo ===
Contributors: tuusuario
Tags: shortcode, ajustes, ejemplo
Requires at least: 5.8
Tested up to: 6.6
Stable tag: 1.0.0
License: GPLv2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html
Plugin de ejemplo con shortcode y página de ajustes.
== Description ==
- Shortcode: [mi_plugin]
- Ajustes en Ajustes > Mi Plugin.
- Seguro, ligero y traducible.
== Installation ==
1. Subir carpeta "mi-plugin" a /wp-content/plugins/.
2. Activar en "Plugins".
3. Usar el shortcode.
== Changelog ==
= 1.0.0 =
* Primera versión.
5) Publicar en WordPress.org (SVN) o GitHub#
svn/
├─ assets/ # banners/iconos del perfil del plugin
├─ trunk/ # código actual
└─ tags/1.0.0/ # snapshot por versión
# Crear tag 1.0.0 desde trunk
svn copy trunk tags/1.0.0 -m "Versión 1.0.0"
svn commit -m "Publicación inicial"
6) Checklist de publicación#
- Version y Stable tag coinciden (1.0.0).
- readme.txt válido y banners en
/assets(icon-256, banner-772×250). - Internacionalización activa (
load_plugin_textdomain). - Pruebas en PHP 7.4–8.3 y WP 6.x; sin avisos con
WP_DEBUG.
FAQ#
¿Cómo uso el shortcode?
Escribe [mi_plugin mensaje="¡Plugin listo!"]Contenido opcional[/mi_plugin] en el editor.
¿Cómo limpio datos al desinstalar?
Añade un archivo uninstall.php con delete_option('mi_plugin_opcion').
¿Te gustaría profundizar en estos temas?
Aprende sobre desarrollo de software, apps a medida, automatizaciones con N8N, Next.js y Cloud con casos reales.


