Cómo funciona realmente la página de blog en WordPress (guía técnica avanzada)

arquitectura-interna-de-la-pagina-de-blog-en-wordpress-nivel-desarrollador

Introducción

La página de blog de WordPress parece sencilla desde fuera: una URL muestra una lista de entradas, normalmente ordenadas de la más reciente a la más antigua, con paginación y quizá filtros por categoría, autor o fecha. Sin embargo, internamente no funciona como una página convencional.

La clave para entenderla a nivel desarrollador es distinguir entre la página que se selecciona en Ajustes > Lectura y la consulta que WordPress construye cuando un visitante solicita la URL del blog. Aunque en el panel de administración exista un objeto de tipo page llamado, por ejemplo, “Blog”, esa página actúa principalmente como referencia de configuración. En el front-end, WordPress transforma la petición en el contexto especial del índice de entradas.

Esta diferencia explica muchos comportamientos que desconciertan incluso a usuarios con experiencia: editar el contenido de la página “Blog” y no verlo publicado, asignarle una plantilla de página y comprobar que se ignora, modificar page.php sin afectar al listado, utilizar is_page() y obtener un resultado inesperado o crear una consulta secundaria que rompe la paginación.

Este artículo recorre el proceso completo desde una perspectiva técnica: configuración, resolución de URL, variables de consulta, WP_Query, etiquetas condicionales, jerarquía de plantillas, Loop, paginación, hooks y depuración. El objetivo no es enseñar a instalar WordPress —para eso conviene consultar cómo instalar WordPress manualmente en un servidor propio—, sino comprender qué ocurre después, cuando el núcleo tiene que decidir qué significa realmente la URL del blog y qué debe renderizar.

Índice

El modelo mental correcto: la página de blog no es una página normal

Para trabajar con WordPress a nivel técnico conviene separar tres conceptos que visualmente pueden parecer lo mismo:

  • la URL solicitada por el navegador;
  • el objeto almacenado en la base de datos que puede servir como referencia para esa URL;
  • el tipo de consulta que WordPress decide ejecutar y que determinará la plantilla y el contenido final.

Una página convencional —por ejemplo, “Contacto”— suele resolverse como una consulta singular de tipo página. WordPress identifica un objeto WP_Post cuyo post_type es page, activa condiciones como is_page() e is_singular() y busca una plantilla dentro de la jerarquía de páginas.

La página asignada como índice de entradas funciona de otra manera. Puede existir en la tabla de contenidos como una página normal y tener ID, título, slug, autor, estado y contenido. Pero cuando su ID queda registrado como page_for_posts, WordPress utiliza esa configuración para reconocer que su URL representa el blog posts index: el índice cronológico de entradas.

Por tanto, hay que abandonar una intuición muy habitual:

URL /blog/
    ↓
Página "Blog"
    ↓
page.php
    ↓
the_content()

En una configuración con portada estática y página de entradas separada, el modelo útil es más parecido a este:

URL /blog/
    ↓
WordPress interpreta la petición
    ↓
Reconoce page_for_posts
    ↓
Construye la consulta principal del índice de entradas
    ↓
is_home() = true
    ↓
Jerarquía "home"
    ↓
home.php / home.html
    ↓
index.php / index.html como fallback
    ↓
Loop con las entradas consultadas

La existencia de una página “Blog” en el administrador no convierte el front-end del blog en una página singular ordinaria. Esa idea es la base de todo lo que viene después.

Qué guardan realmente los Ajustes de lectura

La configuración de Ajustes > Lectura controla una parte decisiva del enrutamiento de WordPress. Tres opciones son especialmente relevantes:

  • show_on_front: indica si la portada muestra las últimas entradas o una página estática;
  • page_on_front: almacena el ID de la página utilizada como portada estática;
  • page_for_posts: almacena el ID de la página asociada al índice de entradas.

Desde PHP pueden inspeccionarse directamente:

$show_on_front = get_option( 'show_on_front' );
$page_on_front = (int) get_option( 'page_on_front' );
$page_for_posts = (int) get_option( 'page_for_posts' );

Si show_on_front vale posts, la URL principal del sitio muestra el índice de entradas. En ese escenario, portada e índice del blog coinciden conceptualmente.

Si show_on_front vale page, WordPress separa ambos papeles. Una página puede actuar como portada mediante page_on_front y otra como índice de entradas mediante page_for_posts.

Ejemplo de configuración

show_on_front = page
page_on_front = 42
page_for_posts = 73

Supongamos que la página con ID 42 tiene el slug inicio y la página con ID 73 tiene el slug blog. La primera se comportará como portada estática. La segunda proporcionará la URL destinada al índice de entradas, pero el contexto de consulta de esa URL será el del blog.

Esta separación es especialmente útil en webs profesionales: la portada puede presentar servicios, productos o información corporativa, mientras que /blog/ queda dedicado al contenido editorial.

Conviene entender esta capa antes de tocar plantillas o plugins. Muchos problemas atribuidos al tema son, en realidad, una interpretación incorrecta de estas opciones y de la función que desempeña cada página.

Qué ocurre cuando llega una petición a la URL del blog

Cuando un navegador solicita una URL amigable como /blog/, WordPress no abre físicamente un archivo llamado blog. La petición entra en la aplicación y debe transformarse en información que el núcleo pueda consultar.

De forma simplificada, el recorrido es el siguiente:

  1. el servidor web recibe la petición HTTP;
  2. las reglas de reescritura hacen que la petición dinámica llegue al punto de entrada de WordPress;
  3. WordPress carga su entorno, plugins y tema;
  4. la clase responsable de la petición interpreta la URL y obtiene variables de consulta;
  5. se crea y prepara la consulta principal;
  6. WP_Query determina qué tipo de vista se está solicitando;
  7. se consultan las entradas que correspondan;
  8. el cargador de plantillas selecciona el recurso adecuado;
  9. el tema ejecuta el Loop o, en un tema de bloques, renderiza el bloque de consulta correspondiente;
  10. se genera la respuesta HTML.

Esta visión por capas resulta muy útil porque evita mezclar responsabilidades. Nginx o Apache se ocupan de servir y encaminar la petición; WordPress interpreta el significado editorial de la URL; WP_Query obtiene los contenidos; y el tema decide cómo presentarlos.

Si quieres profundizar en la capa anterior a WordPress, el artículo qué es realmente un servidor web explica qué papel desempeña el servidor HTTP antes de que el CMS empiece a resolver la página.

Las URLs amigables no sustituyen a las variables de consulta

Los enlaces permanentes ocultan buena parte de la mecánica. Una URL legible se convierte internamente en variables que WordPress utiliza para clasificar la petición. Esa clasificación es esencial porque activa propiedades como is_home, is_page, is_category, is_search o is_404.

En otras palabras, la plantilla no se elige simplemente comparando el texto de la URL con un nombre de archivo. Primero se decide qué tipo de consulta representa esa URL; después se aplica la jerarquía correspondiente.

Cómo se construye la consulta principal con WP_Query

WP_Query es una pieza central de WordPress. Representa una consulta de contenidos y mantiene tanto los parámetros utilizados para obtener entradas como numerosas propiedades que describen el contexto de la petición.

En una visita normal al front-end existe una consulta principal. WordPress la construye automáticamente a partir de la URL, las reglas de reescritura y la configuración del sitio. En el índice del blog, esa consulta suele pedir entradas publicadas, con el orden cronológico configurado por defecto y el número de elementos definido en los Ajustes de lectura.

No debe imaginarse como una consulta SQL escrita directamente por la plantilla. El proceso tiene varias capas:

URL
↓
query vars
↓
WP_Query
↓
normalización y parseo
↓
condicionales de consulta
↓
construcción de SQL
↓
base de datos
↓
colección de objetos WP_Post
↓
Loop

Query vars y estado de la consulta

WP_Query maneja variables como post_type, posts_per_page, paged, category_name, author, s o parámetros de fecha. Además, calcula indicadores internos que permiten saber qué clase de página se está resolviendo.

En el caso del índice de entradas, una de las propiedades importantes es is_home. Cuando WordPress identifica la página configurada como page_for_posts, corrige el contexto para que la petición sea tratada como índice del blog y no como una página singular corriente.

La consulta principal no es un detalle del tema

Un error conceptual frecuente consiste en pensar que home.php “busca las entradas”. En realidad, cuando se llega a la plantilla, WordPress normalmente ya ha preparado y ejecutado la consulta principal. La plantilla consume su resultado.

Esto tiene una consecuencia práctica importante: si lo que quieres es cambiar qué devuelve el índice del blog, suele ser más limpio intervenir antes de ejecutar la consulta que descartar la consulta principal y fabricar otra desde cero dentro de la plantilla.

is_home(), is_front_page() e is_page(): diferencias críticas

Las etiquetas condicionales de WordPress parecen sencillas, pero la página de entradas es uno de los lugares donde más confusión producen.

is_home()

is_home() responde a una pregunta muy concreta: ¿la consulta actual corresponde al índice de entradas del blog?

Si el sitio muestra las últimas entradas directamente en la URL principal, is_home() será verdadero allí. Si existe una portada estática y una página de entradas separada, is_home() será verdadero en la página de entradas.

is_front_page()

is_front_page() comprueba si se está mostrando la portada del sitio, es decir, aquello que aparece en la URL principal.

Por eso pueden darse dos escenarios:

Configuración En la portada En la página de entradas separada
Últimas entradas en portada is_front_page() = true
is_home() = true
No existe como contexto separado
Portada estática + página de entradas is_front_page() = true
is_home() = false
is_front_page() = false
is_home() = true

is_page()

Aquí aparece la sorpresa. Aunque la URL del blog pueda corresponder al slug de un objeto de tipo page seleccionado en Ajustes > Lectura, esa petición se interpreta como el índice de entradas. Por tanto, no debe programarse suponiendo que is_page( 'blog' ) será la condición adecuada para personalizarla.

Para el índice del blog, el indicador semántico correcto es is_home().

Por qué importa esta distinción

Estas condiciones afectan a mucho más que una simple bifurcación visual. Pueden utilizarse en:

  • pre_get_posts para modificar la consulta;
  • carga condicional de CSS o JavaScript;
  • breadcrumbs;
  • títulos secundarios;
  • widgets o bloques específicos;
  • caché;
  • analítica;
  • reglas de personalización del tema.

Usar la condición equivocada puede hacer que el código parezca “no ejecutarse” cuando en realidad el problema está en la identificación del contexto.

Jerarquía de plantillas del índice de entradas

Una vez que WordPress determina que la petición representa el índice del blog, aplica la jerarquía de plantillas correspondiente a Home. El nombre puede resultar engañoso porque “home” no significa necesariamente “portada del dominio”; históricamente se refiere al índice de entradas.

En un tema clásico

Para una página de entradas separada, la ruta habitual es:

home.php
↓
index.php

Si existe home.php, WordPress lo utiliza. Si no existe, recurre a index.php.

Esto explica por qué editar page.php no suele cambiar el listado del blog. La petición no está recorriendo la jerarquía de una página singular.

Cuando el índice del blog está en la portada

Si las últimas entradas aparecen en la propia portada, entra en juego la prioridad especial de la plantilla de front page. En temas clásicos, front-page.php puede tener precedencia sobre home.php. Por eso “portada” e “índice de blog” pueden ser simultáneamente el mismo contexto de contenido pero tener una resolución de plantilla condicionada por la jerarquía de la portada.

No confundir home.php con front-page.php

Una regla práctica útil es:

  • front-page.php: piensa en la URL principal del sitio;
  • home.php: piensa en el índice cronológico de entradas.

Solo coinciden cuando la portada del sitio es también el índice del blog.

index.php es el último recurso del tema clásico

index.php no es únicamente “la plantilla de portada”. En un tema clásico actúa como fallback general. Si no existe una plantilla más específica para el contexto solicitado, WordPress puede terminar allí.

Por eso un tema mínimo puede funcionar con un index.php muy sencillo, mientras que un tema más maduro separa comportamientos mediante archivos específicos.

Diferencias entre temas clásicos y temas de bloques

La arquitectura conceptual de la consulta sigue siendo reconocible en ambos modelos, pero la capa de presentación cambia.

Temas clásicos

Un tema clásico utiliza archivos PHP para componer la respuesta. Es habitual encontrar:

front-page.php
home.php
single.php
page.php
archive.php
search.php
404.php
index.php

La plantilla puede llamar a funciones como get_header(), get_footer(), have_posts(), the_post(), the_title(), the_excerpt() o the_permalink().

Temas de bloques

Los temas de bloques utilizan plantillas HTML de bloques y permiten que determinadas plantillas creadas o modificadas por el usuario se almacenen también en la base de datos. Para el índice de entradas, la jerarquía utiliza conceptos equivalentes:

home.html
↓
index.html

En la portada puede existir además front-page.html, con prioridad propia.

El listado suele construirse mediante un bloque Query y bloques internos como Post Template, Post Title, Post Excerpt, Featured Image y Pagination. Esto reduce la cantidad de PHP visible en la plantilla, pero no elimina el concepto de consulta que hay debajo.

Una diferencia importante de depuración

En un tema de bloques, no basta con inspeccionar los archivos del directorio del tema. Una plantilla personalizada desde el Editor del sitio puede estar guardada como contenido de tipo wp_template en la base de datos y tener prioridad sobre la versión empaquetada por el tema.

Por eso, cuando un cambio en home.html parece no surtir efecto, conviene comprobar si existe una personalización persistida en el Editor del sitio antes de asumir que WordPress está ignorando el archivo.

Esta separación entre contenido, presentación y almacenamiento encaja con una visión más amplia de arquitectura web. Si necesitas ese contexto, puedes ampliar con cómo crear una arquitectura web moderna, evitando confundir la estructura interna de WordPress con la arquitectura completa del sitio.

Cómo el Loop convierte la consulta en una lista de artículos

En un tema clásico, el Loop es el mecanismo que recorre los resultados de la consulta activa. Su forma mínima es conocida:

<?php if ( have_posts() ) : ?>

    <?php while ( have_posts() ) : the_post(); ?>

        <article>
            <h2>
                <a href="<?php the_permalink(); ?>">
                    <?php the_title(); ?>
                </a>
            </h2>

            <?php the_excerpt(); ?>
        </article>

    <?php endwhile; ?>

<?php endif; ?>

have_posts() comprueba si quedan elementos en el conjunto de resultados. the_post() avanza el puntero interno y prepara los datos globales del post actual para que las template tags puedan trabajar con ellos.

El Loop no decide qué entradas existen

Esta distinción es fundamental. El Loop recorre el resultado; no debería ser el lugar donde se redefine arbitrariamente la consulta principal.

Por ejemplo, si quieres que el blog muestre doce entradas por página, no es necesario lanzar una nueva consulta desde home.php. Es más limpio modificar el parámetro posts_per_page de la consulta principal antes de que se ejecute.

Template parts para evitar duplicación

En un tema clásico mantenible, home.php puede delegar el marcado de cada tarjeta de entrada en un template part:

<?php
while ( have_posts() ) :
    the_post();
    get_template_part( 'template-parts/content', 'archive' );
endwhile;
?>

Así se separa la lógica del listado de la estructura visual de cada elemento. La misma pieza puede reutilizarse en archivos de categoría, búsquedas o listados relacionados si el diseño lo justifica.

No convertir el Loop en una acumulación de lógica

Cuantas más decisiones empresariales, consultas auxiliares y transformaciones de datos se introducen directamente en la plantilla, más difícil resulta mantenerla. Una plantilla debería centrarse principalmente en presentación y composición.

Cómo funciona la paginación y por qué se rompe

La página de blog rara vez muestra todas las entradas de una vez. WordPress divide los resultados según el número máximo configurado y utiliza una variable de página para obtener el segmento correspondiente.

En una instalación con enlaces permanentes, las páginas sucesivas pueden adoptar una forma similar a:

/blog/
/blog/page/2/
/blog/page/3/

La consulta principal recibe el contexto de paginación y calcula tanto los resultados de la página actual como el número total de páginas disponible.

Paginación con la consulta principal

En un tema clásico, una vez terminado el Loop puede utilizarse una función como:

<?php
the_posts_pagination(
    array(
        'mid_size'  => 2,
        'prev_text' => 'Anterior',
        'next_text' => 'Siguiente',
    )
);
?>

La ventaja de conservar la consulta principal es que WordPress ya conoce el contexto y dispone de la información necesaria para la navegación.

Por qué una WP_Query secundaria puede romperla

Supongamos que dentro de home.php se ignora la consulta principal y se crea esto:

$blog_query = new WP_Query(
    array(
        'post_type'      => 'post',
        'posts_per_page' => 12,
    )
);

La nueva consulta no recibe automáticamente todo el estado de paginación que estaba asociado a la petición principal. El resultado típico es que la primera página funciona pero /page/2/ repite artículos, muestra un 404 o no avanza correctamente.

Puede repararse pasando paged y gestionando cuidadosamente el total de páginas, pero si la intención era simplemente modificar el listado principal, se ha añadido complejidad innecesaria.

Una regla robusta es conservar la consulta principal siempre que represente exactamente el recurso que estás mostrando.

Cómo modificar la consulta sin sustituirla

El hook pre_get_posts permite intervenir después de crear el objeto de consulta y antes de ejecutar la consulta contra la base de datos. Es uno de los puntos más útiles para personalizar el índice del blog.

Cambiar el número de entradas del blog

function em_ajustar_indice_blog( $query ) {

    if ( is_admin() || ! $query->is_main_query() ) {
        return;
    }

    if ( $query->is_home() ) {
        $query->set( 'posts_per_page', 12 );
    }
}
add_action( 'pre_get_posts', 'em_ajustar_indice_blog' );

Hay dos comprobaciones esenciales:

  • is_admin() evita modificar accidentalmente consultas del área administrativa;
  • $query->is_main_query() limita el cambio a la consulta principal y evita afectar a listados secundarios.

Excluir una categoría concreta

function em_excluir_categoria_blog( $query ) {

    if ( is_admin() || ! $query->is_main_query() ) {
        return;
    }

    if ( $query->is_home() ) {
        $query->set( 'cat', '-27' );
    }
}
add_action( 'pre_get_posts', 'em_excluir_categoria_blog' );

El ejemplo es deliberadamente simple. En un proyecto real conviene documentar por qué se excluye contenido y evitar introducir IDs mágicos sin contexto.

Por qué no conviene usar query_posts()

query_posts() reemplaza la consulta principal y puede generar trabajo adicional, comportamientos difíciles de rastrear y problemas con paginación o estado global. En desarrollos modernos es preferible modificar la consulta existente mediante pre_get_posts o crear una instancia independiente de WP_Query solo cuando de verdad se necesita un listado secundario.

Esta forma de trabajar reduce deuda técnica y encaja con el principio explicado en qué es deuda técnica: una solución rápida puede parecer cómoda hoy y convertirse en una fuente de mantenimiento innecesario mañana.

Consulta principal frente a consultas secundarias

No todas las consultas de una página son iguales. Una plantilla puede necesitar, además del listado principal, un bloque de entradas destacadas, contenidos relacionados, artículos de una categoría concreta o cualquier otro conjunto independiente.

En ese caso sí tiene sentido utilizar una consulta secundaria:

$destacados = new WP_Query(
    array(
        'post_type'      => 'post',
        'posts_per_page' => 3,
        'meta_key'       => 'destacado',
        'meta_value'     => '1',
    )
);

if ( $destacados->have_posts() ) {
    while ( $destacados->have_posts() ) {
        $destacados->the_post();

        // Renderizado del bloque secundario.
    }
}

wp_reset_postdata();

La función wp_reset_postdata() es importante porque the_post() modifica el contexto global del post durante el Loop secundario. Si no se restablece, las template tags ejecutadas después pueden seguir apuntando al último elemento de la consulta auxiliar.

Una página puede contener varias consultas, pero solo una es la principal

El concepto main query no significa “la consulta más grande” ni “la primera que escribe el desarrollador”. Es la consulta que WordPress crea para resolver la petición principal del navegador.

Esto importa especialmente dentro de hooks. Cuando un callback recibe un objeto WP_Query, conviene comprobar el propio método del objeto:

if ( $query->is_main_query() ) {
    // Esta es la consulta principal.
}

Sin esa comprobación, una modificación pensada para el blog puede afectar también a menús, widgets, bloques, consultas relacionadas o componentes de plugins.

Por qué el contenido editado en la página Blog puede no mostrarse

Este es uno de los comportamientos más contraintuitivos para quien llega a WordPress desde un modelo de páginas tradicional.

Se crea una página llamada “Blog”, se escribe una introducción en el editor, quizá se le asigna una plantilla personalizada y después se selecciona como “Página de entradas”. Al visitar /blog/, aparece el listado de artículos pero no el texto escrito.

No es necesariamente un fallo. La página seleccionada está desempeñando un papel especial de configuración y el tema utiliza la jerarquía del índice de entradas. Una plantilla de página asignada a ese objeto no controla automáticamente el resultado.

Entonces, ¿cómo añadir una introducción al blog?

Hay varias estrategias, y la elección depende de cuánto control quieras mantener.

Opción 1: texto fijo en la plantilla

Puede escribirse una introducción directamente en home.php. Es simple, pero mezcla contenido editorial con código y obliga a editar el tema para cambiar el texto.

Opción 2: recuperar explícitamente la página configurada

Una solución más flexible consiste en obtener el ID de page_for_posts y recuperar sus campos expresamente:

$posts_page_id = (int) get_option( 'page_for_posts' );

if ( $posts_page_id ) {
    $title   = get_the_title( $posts_page_id );
    $content = get_post_field( 'post_content', $posts_page_id );

    echo '<h2>' . esc_html( $title ) . '</h2>';
    echo apply_filters( 'the_content', $content );
}

Con esta técnica, el desarrollador decide conscientemente utilizar el contenido del objeto “Blog” como cabecera editorial, sin fingir que la petición es una página singular.

Opción 3: opciones del tema, campos personalizados o bloques

En proyectos más estructurados puede ser preferible guardar la cabecera del blog en opciones, campos específicos o patrones/bloques. La ventaja es separar claramente la configuración del índice del contenido editable.

Lo importante no es elegir siempre la misma técnica, sino conocer el comportamiento por defecto y evitar depender de una coincidencia accidental del tema.

Hooks y puntos de intervención útiles

La arquitectura de WordPress permite intervenir en distintos momentos. Elegir el hook adecuado es más importante que acumular código.

Punto Para qué resulta útil Riesgo habitual
parse_request Observar o intervenir cuando WordPress ha interpretado la petición Modificar demasiado pronto sin entender las reglas de reescritura
parse_query Inspeccionar el estado de una WP_Query después de analizar sus variables Cambiar flags internos de forma incoherente
pre_get_posts Modificar parámetros antes de obtener los posts Afectar consultas secundarias por no comprobar is_main_query()
wp Actuar cuando la consulta ya está resuelta y los posts están cargados Intentar cambiar parámetros que ya deberían haberse aplicado antes
template_include Filtrar la plantilla PHP que finalmente se cargará Romper la jerarquía del tema con rutas frágiles

El hook debe corresponder al problema

Si necesitas cambiar cuántas entradas devuelve el blog, pre_get_posts es un candidato natural. Si necesitas saber qué plantilla se ha elegido, el problema está en una fase posterior. Si lo que falla es una URL, quizá debas mirar antes las reglas de reescritura o las variables de consulta.

Depurar por fases es mucho más eficaz que añadir condicionales al azar en functions.php.

Este criterio también ayuda a reducir dependencia de plugins. El artículo cómo reducir dependencia de WordPress sin perder operativa editorial aborda esa cuestión desde un punto de vista más amplio; aquí la idea concreta es que comprender el ciclo de petición permite resolver algunos problemas en la capa correcta en lugar de instalar extensiones que duplican responsabilidades.

Método de diagnóstico cuando la página de blog no funciona como esperas

Cuando un índice de entradas presenta un comportamiento extraño, conviene seguir un orden de diagnóstico. Saltar directamente a editar plantillas suele hacer perder tiempo.

1. Verificar los Ajustes de lectura

Comprueba si el sitio utiliza “Tus últimas entradas” o “Una página estática”, qué página está seleccionada como portada y cuál como página de entradas.

Desde WP-CLI puede inspeccionarse sin depender del panel:

wp option get show_on_front
wp option get page_on_front
wp option get page_for_posts

Después puede verificarse qué objeto corresponde al ID obtenido:

wp post get 73 --fields=ID,post_title,post_name,post_type,post_status

2. Comprobar el contexto de consulta

Durante una depuración temporal, puede registrarse el estado de las condiciones principales:

add_action( 'wp', function () {

    if ( is_admin() ) {
        return;
    }

    error_log(
        wp_json_encode(
            array(
                'is_home'       => is_home(),
                'is_front_page' => is_front_page(),
                'is_page'       => is_page(),
                'is_archive'    => is_archive(),
                'is_singular'   => is_singular(),
            )
        )
    );
} );

Este tipo de comprobación responde rápidamente a una pregunta esencial: ¿WordPress está interpretando la URL como yo creo?

3. Identificar la plantilla real

Si el contexto es correcto pero el diseño no corresponde, hay que comprobar qué plantilla se ha seleccionado. En un tema clásico puede añadirse temporalmente un filtro de diagnóstico:

add_filter( 'template_include', function ( $template ) {
    error_log( 'Plantilla: ' . $template );
    return $template;
} );

En un tema de bloques, además de los archivos del tema, hay que revisar posibles personalizaciones guardadas mediante el Editor del sitio.

4. Revisar pre_get_posts y filtros de terceros

Si faltan artículos, el orden es extraño o la paginación falla, busca callbacks que modifiquen la consulta. Un plugin, el tema o código propio pueden cambiar posts_per_page, categorías, orden, tipos de contenido o parámetros de fecha.

5. Separar problema de consulta y problema de renderizado

Si la consulta devuelve los posts correctos pero no se ven, el problema está probablemente en la plantilla o en el Loop. Si la consulta ya llega mal, cambiar HTML no solucionará nada.

6. Revisar cachés después, no antes

La caché puede ocultar cambios y complicar la depuración, pero no debe convertirse en explicación universal. Primero verifica la lógica; después limpia o invalida las capas de caché pertinentes.

En un entorno autoalojado, mantener una arquitectura legible facilita enormemente estas tareas. Si la web corre sobre Nginx, el artículo cómo proteger WordPress desde Nginx trata la capa de seguridad del servidor sin mezclarla con la resolución interna del índice de entradas.

Cómo diseñar una página de blog mantenible

Una página de blog técnicamente limpia no necesita una gran cantidad de código. Necesita responsabilidades claras.

Deja que WordPress resuelva la petición

Si la URL representa el índice normal de entradas, aprovecha la consulta principal. No reconstruyas manualmente aquello que el núcleo ya sabe resolver.

Personaliza la consulta antes de ejecutarla

Cuando necesites cambios pequeños —cantidad de artículos, exclusiones, orden o filtros concretos— utiliza el mecanismo apropiado y limita el efecto a is_home() y a la consulta principal.

Mantén la presentación en la plantilla

home.php debería ser entendible al abrirlo. Si contiene consultas SQL directas, llamadas externas, transformación compleja de datos y decenas de reglas empresariales, la plantilla está asumiendo demasiadas responsabilidades.

Reutiliza componentes

Las tarjetas de artículo, metadatos, imágenes destacadas y fragmentos pueden encapsularse en template parts o patrones. Así es más fácil mantener coherencia entre blog, categorías, búsquedas y otros listados.

Evita que cada plugin altere la consulta principal

En una web que crece, varios plugins pueden intentar intervenir sobre el mismo contexto. Cuantas más capas desconocidas modifiquen la consulta, más difícil será explicar por qué un artículo aparece, desaparece o cambia de posición.

Esta es una aplicación concreta del criterio desarrollado en cómo independizarte de plugins pesados: no se trata de eliminar extensiones por principio, sino de conocer qué función crítica asume cada una y evitar dependencias opacas.

Documenta las decisiones no evidentes

Si el blog excluye ciertas categorías, usa un número de entradas distinto o recupera contenido adicional desde page_for_posts, documenta el motivo. Un futuro administrador debería poder comprender el diseño sin reconstruirlo mediante ensayo y error.

Para proyectos con una vida útil larga, esta disciplina suele aportar más valor que una personalización espectacular pero difícil de mantener.

Errores técnicos frecuentes

Tratar la página de entradas como una página singular

Es el error raíz. Lleva a editar page.php, usar is_page() o asignar una plantilla de página esperando que controle el índice.

Confundir home con front page

En WordPress, “home” tiene un significado histórico asociado al índice de posts. La portada real se identifica con el contexto de front page. En una configuración con portada estática son dos URLs y dos contextos distintos.

Crear una segunda WP_Query sin necesidad

Sustituir la consulta principal por otra dentro de home.php suele complicar paginación, estado global y compatibilidad con plugins.

Modificar todas las consultas desde pre_get_posts

Un callback sin is_admin(), is_main_query() y la condición contextual apropiada puede alterar listados que no tienen relación con el blog.

Olvidar wp_reset_postdata()

Después de un Loop secundario, el contexto global puede quedar apuntando al último post de esa consulta y provocar títulos, enlaces o metadatos incorrectos más adelante.

Editar el archivo correcto del tema equivocado

Puede ocurrir con child themes, temas de bloques o plantillas personalizadas guardadas en base de datos. Antes de editar, verifica qué tema está activo y qué plantilla se está utilizando realmente.

Resolver con CSS un problema de arquitectura

Ocultar elementos o recolocar contenido visualmente no corrige una consulta incorrecta ni una plantilla mal elegida. Primero hay que arreglar la capa responsable.

Introducir una solución difícil de actualizar

Modificar directamente un tema de terceros puede perderse al actualizarlo. Si la personalización es propia, conviene utilizar un child theme, un plugin específico del sitio o la extensión adecuada según el tipo de cambio.

Para una visión más general sobre mantener un proyecto WordPress frente a otras arquitecturas, puedes consultar WordPress vs HUGO para proyectos serios. Ese artículo compara plataformas; este se concentra exclusivamente en el mecanismo interno que genera el índice de entradas de WordPress.

Preguntas frecuentes

¿La página de Blog de WordPress es realmente una Page?

Puede existir como un objeto de tipo page en la base de datos y ser seleccionada en Ajustes > Lectura, pero cuando actúa como página de entradas su URL se procesa como el índice del blog. Por eso el contexto y la jerarquía de plantillas no son los de una página singular convencional.

¿Qué plantilla controla la página de entradas en un tema clásico?

Normalmente WordPress busca home.php y, si no existe, utiliza index.php. Si el índice de entradas coincide con la portada del sitio, la plantilla especial front-page.php puede tener prioridad.

¿Qué plantilla controla la página de entradas en un tema de bloques?

El equivalente principal es home.html, con index.html como fallback. En la portada puede intervenir front-page.html. Además, una plantilla personalizada guardada desde el Editor del sitio puede prevalecer sobre el archivo suministrado por el tema.

¿Por qué no aparece el contenido que escribí en la página llamada Blog?

Porque al asignarla como página de entradas WordPress utiliza esa referencia para el índice cronológico y no la procesa automáticamente como una página singular con su contenido habitual. Si quieres mostrar ese texto, la plantilla puede recuperarlo expresamente mediante el ID almacenado en page_for_posts o utilizar otro mecanismo editorial.

¿Debo usar is_page(‘blog’) para detectar el índice del blog?

No como criterio principal. La etiqueta adecuada para el índice de entradas es is_home(). is_front_page() se reserva para la portada del sitio.

¿Cuál es la mejor forma de cambiar el número de artículos del blog?

Si solo necesitas ajustar la consulta principal, puedes utilizar los Ajustes de lectura o modificarla mediante pre_get_posts, comprobando que no estás en administración, que se trata de la consulta principal y que $query->is_home() es verdadero.

¿WP_Query y el Loop son lo mismo?

No. WP_Query representa y ejecuta la consulta de contenidos. El Loop recorre los resultados y prepara cada post para renderizarlo mediante las funciones de plantilla.

¿Es malo crear una WP_Query dentro de home.php?

No por definición. Es correcto para listados secundarios que tengan una finalidad distinta. El problema aparece cuando se crea otra consulta solo para sustituir innecesariamente la consulta principal que WordPress ya había preparado para el índice del blog.

¿Por qué funciona la primera página del blog pero falla /page/2/?

Una causa frecuente es haber sustituido la consulta principal por una consulta personalizada sin transferir correctamente el parámetro de paginación ni utilizar el total de páginas adecuado. También pueden intervenir reglas de reescritura, plugins o modificaciones de pre_get_posts.

¿Necesito un plugin para personalizar la página de blog?

No necesariamente. Muchas personalizaciones de consulta, plantilla y Loop pueden resolverse con mecanismos nativos de WordPress. Un plugin puede ser útil cuando aporta una función clara y mantenible, pero no debería sustituir la comprensión del contexto de consulta y la jerarquía de plantillas.

Conclusión

La página de blog de WordPress se entiende mucho mejor cuando deja de verse como “una página que contiene entradas” y se analiza como un contexto de consulta especial.

La página seleccionada en Ajustes > Lectura proporciona una referencia y una URL, pero el núcleo reconoce esa petición como índice de entradas. A partir de ahí, WP_Query prepara la consulta principal, is_home() identifica el contexto, la jerarquía busca la plantilla adecuada y el Loop transforma los resultados en HTML.

Ese recorrido explica por qué page.php puede no intervenir, por qué el contenido del editor de la página Blog no aparece automáticamente, por qué home.php no significa necesariamente portada, por qué una consulta secundaria mal planteada rompe la paginación y por qué pre_get_posts es un punto de extensión mucho más limpio que reemplazar la consulta principal.

Comprender esta arquitectura permite personalizar WordPress con menos código, diagnosticar problemas con más precisión y mantener el sitio sin convertir cada cambio editorial en una excepción técnica.

En proyectos pequeños o con recursos limitados, esa comprensión tiene un valor práctico especial: permite utilizar WordPress como herramienta editorial potente sin tratarlo como una caja negra y sin añadir capas innecesarias cada vez que el comportamiento por defecto no coincide exactamente con lo que necesita el sitio.

Written by