---
title: "Cheat sheet para creadores de temas WordPress (Classic + Block Themes/FSE)"
description: "Si desarrollas temas para WordPress, probablemente tienes decenas de pestañas abiertas buscando el nombre exacto de un hook, la jerarquía de plantillas o la sintaxis correcta de theme.json. Esta guía..."
url: https://wpdirecto.com/hoja-de-ayuda-para-creadores-de-plantillas-para-wordpress/
date: 2012-02-04
modified: 2026-05-07
author: "David Carrero Fernández-Baillo"
image: https://wpdirecto.com/wp-content/uploads/2026/05/ai-clean-developer-cheat-sheet-reference-guide-for-wordpress-th-d4mUEU.png
categories: ["Desarrollo", "Temas y diseño"]
tags: ["accesibilidad", "action hooks", "block themes", "crear temas WordPress", "Full Site Editing", "plantillas", "theme.json", "themes", "wordpress", "wp-cli"]
type: post
lang: es
---

# Cheat sheet para creadores de temas WordPress (Classic + Block Themes/FSE)

Si desarrollas temas para WordPress, probablemente tienes decenas de pestañas abiertas buscando el nombre exacto de un hook, la jerarquía de plantillas o la sintaxis correcta de theme.json. Esta guía de referencia rápida te da todo eso en un solo lugar, actualizada: tanto si trabajas con temas clásicos como si ya te has pasado a los Block Themes y el Full Site Editing (FSE).

A diferencia de la cheat sheet original de 2012 que publicamos aquí, esta versión cubre desde los hooks fundamentales de siempre hasta la estructura de `theme.json` y los comandos WP-CLI que más usarás en el día a día. Guárdala en favoritos o imprímela: vas a volver a ella.

## 1. Anatomía de un tema clásico de WordPress

Un tema clásico se construye con una jerarquía de archivos PHP que WordPress carga según el contexto de la página. Aquí tienes los archivos esenciales:

| Archivo | Cuándo se usa |
| --- | --- |
| `index.php` | Plantilla de reserva universal (obligatoria) |
| `style.css` | Hoja de estilos principal + cabecera de metadatos del tema (obligatoria) |
| `functions.php` | Registro de funciones, hooks, enqueue de scripts/styles |
| `header.php` | Cabecera del sitio, cargada con `get_header()` |
| `footer.php` | Pie de página, cargado con `get_footer()` |
| `sidebar.php` | Barra lateral, cargada con `get_sidebar()` |
| `single.php` | Entrada individual de blog |
| `page.php` | Página estática |
| `archive.php` | Páginas de archivo (categorías, etiquetas, fechas) |
| `category.php` | Archivo de categoría (sobrescribe archive.php) |
| `tag.php` | Archivo de etiqueta |
| `search.php` | Resultados de búsqueda |
| `404.php` | Página de error 404 |
| `home.php` | Listado de entradas del blog (cuando la portada es estática) |
| `front-page.php` | Portada del sitio (estática o dinámica) |
| `singular.php` | Plantilla compartida para single + page (WP 4.3+) |
| `comments.php` | Área de comentarios |
| `attachment.php` | Páginas de adjuntos |
| `screenshot.png` | Captura de pantalla (880×660 px) para el directorio de temas |

La jerarquía de plantillas funciona de más específico a más genérico. WordPress busca el archivo más específico disponible y, si no lo encuentra, sube en la cadena hasta llegar a `index.php`.

## 2. Anatomía de un Block Theme (FSE)

Los Block Themes, introducidos de forma estable en WordPress 5.9, cambian la estructura completamente. Ya no hay archivos PHP de plantilla: todo se define con bloques HTML en archivos `.html`, y la configuración global del tema vive en `theme.json`.

| Archivo / Carpeta | Función |
| --- | --- |
| `style.css` | Cabecera de metadatos del tema (obligatoria, puede estar vacía) |
| `theme.json` | Configuración global: colores, tipografía, espaciado, bloques |
| `templates/` | Plantillas de página en formato HTML con bloques (index.html obligatorio) |
| `parts/` | Partes reutilizables: header.html, footer.html, sidebar.html |
| `patterns/` | Patrones de bloques registrados automáticamente |
| `functions.php` | Opcional: enqueue de scripts adicionales, hooks PHP |
| `assets/` | Imágenes, fonts, JS/CSS personalizados |

### Plantillas mínimas en un Block Theme

```
mi-tema/
├── style.css          # Cabecera con Theme Name, Version, etc.
├── theme.json         # Configuración global
├── templates/
│   ├── index.html     # Obligatoria
│   ├── single.html
│   ├── page.html
│   ├── archive.html
│   ├── search.html
│   └── 404.html
└── parts/
    ├── header.html
    └── footer.htmlLenguaje del código: PHP (php)
```

## 3. theme.json — estructura y ejemplo práctico

`theme.json` es el corazón de la configuración de un Block Theme (aunque también funciona en temas clásicos desde WP 5.8). Controla la paleta de colores, tipografía, espaciado y qué opciones del editor están disponibles para el usuario.

```
{
  "$schema": "https://schemas.wp.org/trunk/theme.json",
  "version": 3,
  "settings": {
    "color": {
      "palette": [
        { "slug": "primary",    "color": "#1a73e8", "name": "Primary" },
        { "slug": "secondary",  "color": "#f8f9fa", "name": "Secondary" },
        { "slug": "dark",       "color": "#202124", "name": "Dark" }
      ],
      "custom": false,
      "customDuotone": false
    },
    "typography": {
      "fontFamilies": [
        {
          "slug": "system",
          "name": "System UI",
          "fontFamily": "-apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif"
        }
      ],
      "fontSizes": [
        { "slug": "sm",   "size": "0.875rem", "name": "Small" },
        { "slug": "base", "size": "1rem",     "name": "Base" },
        { "slug": "lg",   "size": "1.25rem",  "name": "Large" },
        { "slug": "xl",   "size": "1.5rem",   "name": "Extra Large" }
      ],
      "customFontSize": false
    },
    "spacing": {
      "spacingSizes": [
        { "slug": "sm",  "size": "1rem",  "name": "Small" },
        { "slug": "md",  "size": "2rem",  "name": "Medium" },
        { "slug": "lg",  "size": "4rem",  "name": "Large" }
      ],
      "customSpacingSize": false
    },
    "layout": {
      "contentSize": "800px",
      "wideSize": "1200px"
    }
  },
  "styles": {
    "color": {
      "background": "var(--wp--preset--color--secondary)",
      "text": "var(--wp--preset--color--dark)"
    },
    "typography": {
      "fontFamily": "var(--wp--preset--font-family--system)",
      "fontSize": "var(--wp--preset--font-size--base)",
      "lineHeight": "1.7"
    },
    "elements": {
      "link": {
        "color": { "text": "var(--wp--preset--color--primary)" }
      }
    }
  }
}Lenguaje del código: JSON / JSON con comentarios (json)
```

## 4. Hooks principales de WordPress

Los hooks son el mecanismo central para personalizar WordPress sin tocar el núcleo. Hay dos tipos: **acciones** (`add_action`) que ejecutan código en un momento concreto, y **filtros** (`add_filter`) que modifican datos antes de que se usen.

### Hooks de acción esenciales

| Hook | Cuándo se dispara | Uso típico |
| --- | --- | --- |
| `after_setup_theme` | Tras cargar el tema | add_theme_support(), register_nav_menus() |
| `init` | Después de cargar WP, antes de headers | Registrar CPTs, taxonomías, shortcodes |
| `wp_enqueue_scripts` | Front-end, para encolar assets | wp_enqueue_style(), wp_enqueue_script() |
| `admin_enqueue_scripts` | Back-end, para encolar assets del admin | Scripts/styles solo en wp-admin |
| `wp_head` | Dentro de `<head>` | Meta tags, estilos inline críticos |
| `wp_body_open` | Justo tras `<body>` | GTM, banners de cookies |
| `wp_footer` | Antes de cerrar `</body>` | Scripts diferidos, chat widgets |
| `save_post` | Al guardar/actualizar una entrada | Metadatos personalizados, invalidar caché |
| `widgets_init` | Al inicializar widgets | register_sidebar() |
| `template_redirect` | Antes de determinar la plantilla | Redirecciones condicionales |
| `wp_loaded` | WordPress completamente cargado | Lógica que necesita todo WP listo |
| `the_post` | Dentro del loop, al configurar la entrada | Modificar datos del post actual |

### Hooks de filtro esenciales

| Filtro | Qué modifica |
| --- | --- |
| `the_content` | Contenido del post antes de mostrarse |
| `the_title` | Título del post en el front-end |
| `excerpt_length` | Longitud del extracto automático |
| `excerpt_more` | Texto «[…]» al final del extracto |
| `wp_title` | Título de la página (legacy, usar wp_head) |
| `body_class` | Clases CSS del elemento `<body>` |
| `post_class` | Clases CSS de cada entrada en el loop |
| `upload_mimes` | Tipos MIME permitidos en subidas |
| `login_redirect` | URL de redirección tras el login |
| `allowed_block_types_all` | Bloques de Gutenberg disponibles (FSE) |
| `block_editor_settings_all` | Configuración global del editor de bloques |

### Sintaxis rápida

```
// Acción: ejecutar código en un punto concreto
add_action( 'after_setup_theme', function() {
    add_theme_support( 'post-thumbnails' );
    add_theme_support( 'title-tag' );
    add_theme_support( 'html5', [ 'search-form', 'comment-form', 'gallery', 'caption' ] );
    register_nav_menus( [ 'primary' => __( 'Menú principal', 'mi-tema' ) ] );
} );

// Filtro: modificar datos antes de su uso
add_filter( 'excerpt_length', function( $length ) {
    return 25; // palabras
} );

// Prioridad y argumentos (por defecto: prioridad 10, 1 argumento)
add_action( 'save_post', 'mi_funcion_guardar', 20, 2 );
add_filter( 'the_content', 'mi_filtro_contenido', 15, 1 );Lenguaje del código: PHP (php)
```

## 5. Template tags más usados

Las template tags son funciones PHP de WordPress para mostrar datos dentro de las plantillas. Estas son las que usarás constantemente:

| Función | Qué devuelve / hace |
| --- | --- |
| `the_title()` | Imprime el título del post actual |
| `get_the_title( $id )` | Devuelve el título (sin imprimir) |
| `the_content()` | Imprime el contenido del post con filtros aplicados |
| `the_excerpt()` | Imprime el extracto (automático o manual) |
| `the_permalink()` | Imprime la URL del post actual |
| `get_permalink( $id )` | Devuelve la URL del post (sin imprimir) |
| `the_ID()` | Imprime el ID del post actual |
| `get_the_ID()` | Devuelve el ID del post (sin imprimir) |
| `the_post_thumbnail( $size )` | Imprime la imagen destacada |
| `get_template_part( $slug, $name )` | Incluye una parte de plantilla reutilizable |
| `get_header()` | Incluye header.php |
| `get_footer()` | Incluye footer.php |
| `get_sidebar()` | Incluye sidebar.php |
| `get_post_meta( $id, $key, true )` | Devuelve un metadato personalizado |
| `get_field( $name )` | Devuelve un campo de ACF (requiere plugin) |
| `bloginfo( 'name' )` | Nombre del sitio |
| `get_bloginfo( 'url' )` | URL del sitio (devuelve, no imprime) |
| `home_url( '/' )` | URL de la portada del blog |
| `get_template_directory_uri()` | URL del directorio del tema activo |
| `get_stylesheet_directory_uri()` | URL del tema hijo (o padre si no hay hijo) |
| `has_post_thumbnail()` | Comprueba si el post tiene imagen destacada |

## 6. Enqueue correcto de scripts y estilos

Uno de los errores más comunes en temas antiguos es cargar scripts con `<script>` directo en las plantillas. La forma correcta desde hace años es usar el sistema de enqueue de WordPress, que gestiona dependencias y evita duplicados.

```
add_action( 'wp_enqueue_scripts', 'mi_tema_enqueue_assets' );
function mi_tema_enqueue_assets() {

    // Estilo principal (versión = versión del tema)
    wp_enqueue_style(
        'mi-tema-main',
        get_stylesheet_uri(),
        [],
        wp_get_theme()->get( 'Version' )
    );

    // Script con dependencias y defer
    wp_enqueue_script(
        'mi-tema-main-js',
        get_template_directory_uri() . '/assets/js/main.js',
        [ 'jquery' ],       // dependencias
        '1.0.0',
        [ 'strategy' => 'defer', 'in_footer' => true ] // WP 6.3+
    );

    // Pasar variables PHP a JS
    wp_localize_script( 'mi-tema-main-js', 'miTema', [
        'ajaxUrl' => admin_url( 'admin-ajax.php' ),
        'nonce'   => wp_create_nonce( 'mi-tema-nonce' ),
    ] );
}

// Solo en páginas de administración
add_action( 'admin_enqueue_scripts', function( $hook ) {
    if ( 'post.php' !== $hook ) return;
    wp_enqueue_style( 'mi-admin-style', get_template_directory_uri() . '/assets/css/admin.css' );
} );Lenguaje del código: PHP (php)
```

## 7. Escapado seguro, nonces y traducciones

La seguridad no es opcional en el desarrollo de temas. Estas son las funciones que debes usar siempre antes de imprimir cualquier dato externo o recibido del usuario:

### Funciones de escapado

| Función | Cuándo usarla |
| --- | --- |
| `esc_html( $str )` | Texto genérico dentro de HTML (evita XSS) |
| `esc_attr( $str )` | Valores de atributos HTML (`class`, `id`, `data-*`) |
| `esc_url( $url )` | URLs en `href`, `src`, etc. |
| `esc_textarea( $str )` | Contenido dentro de `<textarea>` |
| `esc_js( $str )` | Cadenas dentro de bloques JavaScript inline |
| `wp_kses_post( $html )` | HTML del que quieres permitir solo etiquetas seguras |
| `absint( $num )` | Enteros positivos (IDs, contadores) |
| `intval( $num )` | Enteros (positivos y negativos) |

### Nonces (verificación de intención)

```
// Crear nonce en formulario
wp_nonce_field( 'guardar_metadatos', 'mi_nonce_field' );

// Verificar nonce al procesar
if ( ! isset( $_POST['mi_nonce_field'] ) ||
     ! wp_verify_nonce( $_POST['mi_nonce_field'], 'guardar_metadatos' ) ) {
    wp_die( 'Verificación de seguridad fallida.' );
}

// Nonce en URL (para enlaces de acción)
$url = wp_nonce_url( admin_url( 'admin.php?action=mi-accion' ), 'mi-accion-nonce' );Lenguaje del código: PHP (php)
```

### Funciones de traducción (i18n)

```
// Texto traducible (devuelve)
$texto = __( 'Leer más', 'mi-tema' );

// Texto traducible (imprime directamente)
_e( 'Publicado el', 'mi-tema' );

// Con contexto para el traductor
$texto = _x( 'Ver', 'botón de acción', 'mi-tema' );

// Plurales
$texto = _n( '%d comentario', '%d comentarios', $count, 'mi-tema' );

// Escapado + traducción en una línea (más seguro)
esc_html_e( 'Buscar', 'mi-tema' );
$safe = esc_html__( 'Resultados', 'mi-tema' );

// Registrar el dominio de texto en functions.php
add_action( 'after_setup_theme', function() {
    load_theme_textdomain( 'mi-tema', get_template_directory() . '/languages' );
} );Lenguaje del código: PHP (php)
```

## 8. Accesibilidad básica en temas WordPress

WordPress tiene [un equipo dedicado a accesibilidad](https://make.wordpress.org/accessibility/) y los temas del directorio oficial deben cumplir unas normas mínimas. Aunque no publiques en el directorio, seguir estas convenciones mejora la experiencia de todos los usuarios y ayuda al SEO:

- Usa `add_theme_support( 'html5', ['search-form', 'comment-form', 'comment-list', 'gallery', 'caption', 'style', 'script'] )` para markup HTML5 semántico.
- Añade `skip navigation link` como primer elemento tras \`\` (con `wp_body_open`).
- Todos los \`\` deben tener atributo `alt`; usa `esc_attr( get_post_meta( $id, '_wp_attachment_image_alt', true ) )`.
- Los menús deben tener `aria-label` descriptivo: \`\`.
- Asegura relación de contraste mínima de 4.5:1 para texto normal (WCAG 2.1 AA).
- Botones e inputs deben ser navegables por teclado y tener focus visible.

## 9. Comandos WP-CLI esenciales para desarrollo de temas

WP-CLI es la herramienta de línea de comandos oficial de WordPress. Si no la usas en tu flujo de desarrollo de temas, te estás complicando la vida innecesariamente. Estos son los comandos que más valor aportan:

```
# Crear un tema hijo a partir de un tema existente
wp scaffold child-theme mi-tema-hijo --parent_theme=twentytwentyfive

# Crear tema desde cero (estructura básica)
wp scaffold _s mi-tema --theme_name="Mi Tema" --author="Tu Nombre" --activate

# Listar temas instalados
wp theme list

# Activar un tema
wp theme activate mi-tema

# Ver detalles de un tema
wp theme get twentytwentyfive --fields=name,version,status

# Buscar temas en el repositorio oficial
wp theme search "minimalist" --per-page=5

# Actualizar todos los temas
wp theme update --all

# Exportar contenido de demostración
wp export --post_type=post --post_status=publish --filename_format=demo-content.xml

# Evaluar código PHP rápido
wp eval 'echo get_template_directory();'

# Vaciar caché de objetos
wp cache flush

# Regenerar miniaturas después de cambiar tamaños de imagen
wp media regenerate --yes

# Ver hooks disponibles (requiere plugin Query Monitor)
wp eval 'do_action( "wp_head" );'

# Exportar base de datos
wp db export backup.sql

# Buscar y reemplazar URL (migraciones)
wp search-replace 'https://old-domain.com' 'https://new-domain.com' --precise --recurse-objectsLenguaje del código: PHP (php)
```

Si quieres sacar más partido al rendimiento de tu tema, te recomendamos leer nuestra guía sobre [cómo mejorar el rendimiento de WordPress](https://wpdirecto.com/consejos-para-mejorar-el-rendimiento-de-wordpress/). Y si trabajas con el .htaccess del servidor, esta otra sobre [trucos útiles para el .htaccess de WordPress](https://wpdirecto.com/15-cosas-que-se-pueden-hacer-modificando-el-htaccess-de-wordpress/) te será muy práctica.

## 10. Convenciones modernas que debes aplicar siempre

Más allá de los hooks y funciones concretas, hay una serie de convenciones que separan un tema mantenible de uno que se convierte en deuda técnica a los seis meses:

- **Prefija siempre tus funciones**: usa `mi_tema_` como prefijo para evitar conflictos con plugins. Nunca nombres genéricos como `get_data()`.
- **Usa temas hijo para personalizaciones**: nunca modifiques un tema padre directamente; perderás los cambios con cada actualización. Para plugins, revisa cuáles son [seguros en la cadena de suministro](https://wpdirecto.com/wp-beacon-vigila-la-cadena-de-suministro-de-plugins-de-wordpress/).
- **Sanitiza entradas, escapa salidas**: usa `sanitize_text_field()`, `absint()`, etc. al guardar datos del usuario; usa `esc_html()`, `esc_url()`, etc. al mostrarlos.
- **No pongas lógica compleja en plantillas**: las plantillas solo deben mostrar datos. La lógica va en `functions.php` o en archivos PHP organizados en una carpeta `inc/`.
- **Versiona tus assets**: pasa el hash del archivo como versión en `wp_enqueue_*` para invalidar caché al actualizar. Usa `filemtime( get_template_directory() . '/assets/css/main.css' )` durante desarrollo.
- **Evita dependencias de jQuery innecesarias**: el JavaScript moderno (ES6+) puede hacer casi todo sin jQuery. Pesa menos y evita conflictos de versiones.
- **Block Theme: usa `theme.json` para todo lo que puedas**: colores, espaciado, tipografía. Evita CSS hardcoded; así el usuario puede cambiar el tema visual desde el editor sin tocar código.

## Preguntas frecuentes sobre desarrollo de temas WordPress

### ¿Debo aprender Block Themes o seguir con temas clásicos?

Depende del proyecto y del cliente. Los temas clásicos siguen siendo perfectamente válidos y tendrán soporte durante años. Sin embargo, si estás empezando un proyecto nuevo y el cliente usará el editor de WordPress activamente, los Block Themes ofrecen una experiencia de edición mucho más fluida. Lo ideal es dominar ambos paradigmas: la base PHP de los temas clásicos y la filosofía de theme.json y FSE de los Block Themes.

### ¿Cuál es la diferencia entre `get_template_directory()` y `get_stylesheet_directory()`?

`get_template_directory()` siempre apunta al tema padre, mientras que `get_stylesheet_directory()` apunta al tema activo (que en un tema hijo sería el hijo, no el padre). Si estás en un tema sin hijo, ambas devuelven lo mismo. Para incluir archivos en un tema hijo, usa siempre `get_stylesheet_directory()`; para cargar assets del tema padre explícitamente, usa `get_template_directory()`.

### ¿Cómo registro soporte para características del núcleo de WordPress en mi tema?

Usa `add_theme_support()` dentro del hook `after_setup_theme`. Las características más comunes son: `post-thumbnails` (imágenes destacadas), `title-tag` (delega el título al núcleo), `html5` (markup moderno), `custom-logo`, `automatic-feed-links` y `editor-styles`. Para Block Themes modernos, muchas de estas se activan automáticamente, pero sigue siendo buena práctica declararlas explícitamente en `functions.php`.

### ¿theme.json funciona en temas clásicos?

Sí. Desde WordPress 5.8, `theme.json` está disponible también para temas clásicos, aunque con algunas limitaciones respecto a los Block Themes. Puedes usarlo para definir la paleta de colores del editor, tamaños de fuente personalizados y espaciado, lo que da al editor de bloques una experiencia más coherente con el diseño de tu tema clásico incluso sin FSE completo.

### ¿Cómo evito que WordPress cargue el plugin de caché en el área de administración?

Esto no es específico del tema, pero afecta al rendimiento en desarrollo. La mayoría de plugins de caché excluyen el admin automáticamente. Si tu tema añade páginas de administración con assets pesados, recuerda usar `admin_enqueue_scripts` con verificación del hook concreto (`$hook`) en lugar de cargar en todas las páginas del admin. Puedes leer más sobre [los mejores plugins de caché para WordPress](https://wpdirecto.com/encuesta-cual-es-el-mejor-plugin-de-cache-para-wordpress/) en nuestra comparativa actualizada.
