<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/">
	<channel>
		<title><![CDATA[PHPost | Soporte, Descargas y Tutoriales de Risus Nova - Todos los foros]]></title>
		<link>https://phpost.es/</link>
		<description><![CDATA[PHPost | Soporte, Descargas y Tutoriales de Risus Nova - https://phpost.es]]></description>
		<pubDate>Sun, 19 Jul 2026 23:25:14 +0000</pubDate>
		<generator>MyBB</generator>
		<item>
			<title><![CDATA[Risus Nova UI 1.0]]></title>
			<link>https://phpost.es/tema-Dise%C3%B1os-terminados-Risus-Nova-UI-1-0</link>
			<pubDate>Sun, 19 Jul 2026 16:05:25 +0200</pubDate>
			<dc:creator><![CDATA[<a href="https://phpost.es/member.php?action=profile&uid=1">Tronlar</a>]]></dc:creator>
			<guid isPermaLink="false">https://phpost.es/tema-Dise%C3%B1os-terminados-Risus-Nova-UI-1-0</guid>
			<description><![CDATA[<div style="text-align: center;" class="mycode_align"><span style="color: #2980b9;" class="mycode_color"><span style="font-size: x-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Risus Nova UI 1.0</span></span></span></div>
<div style="text-align: center;" class="mycode_align"><span style="font-size: large;" class="mycode_size">Rediseño completo de la interfaz de Risus Nova, basado en CoreUI (Bootstrap 5), con modo oscuro incluido.</span></div>
<br />
<br />
<span style="font-weight: bold;" class="mycode_b"><span style="color: #2980b9;" class="mycode_color"><span style="font-size: x-large;" class="mycode_size">DEMO</span></span></span><br />
<a href="http://Registrate%20o%20inicia%20tu%20sesión%20para%20ver%20este%20contenido" target="_blank" rel="noopener" class="mycode_url">http://Registrate o inicia tu sesión par... contenido</a><br />
<br />
<br />
<span style="color: #2980b9;" class="mycode_color"><span style="font-size: x-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Capturas</span></span></span><br />
 <br />
<div style="text-align: center;" class="mycode_align"><img src="https://i.imgur.com/ecLwmLn.png" loading="lazy"  alt="[Imagen: ecLwmLn.png]" class="mycode_img img-responsive" /></div>
<div style="text-align: center;" class="mycode_align"><img src="https://i.imgur.com/CUpxLBC.png" loading="lazy"  alt="[Imagen: CUpxLBC.png]" class="mycode_img img-responsive" /></div>
<div style="text-align: center;" class="mycode_align"><img src="https://i.imgur.com/4m0X0Xp.png" loading="lazy"  alt="[Imagen: 4m0X0Xp.png]" class="mycode_img img-responsive" /></div>
<div style="text-align: center;" class="mycode_align"><img src="https://i.imgur.com/UYTV5qI.png" loading="lazy"  alt="[Imagen: UYTV5qI.png]" class="mycode_img img-responsive" /></div>
<div style="text-align: center;" class="mycode_align"><img src="https://i.imgur.com/v84x7Gl.png" loading="lazy"  alt="[Imagen: v84x7Gl.png]" class="mycode_img img-responsive" /></div>
<br />
<br />
<br />
<span style="font-size: x-large;" class="mycode_size"><span style="color: #2980b9;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">¿Qué incluye?</span></span></span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size">Rediseño completo con CoreUI (Bootstrap 5) en lugar de la maquetación clásica.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Modo claro / oscuro / automático (según el sistema).</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Iconos de CoreUI Icons Free en la barra lateral.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Compatible con Risus Nova 2.1.5.</span><br />
</li>
</ul>
<br />
<br />
<br />
<span style="color: #2980b9;" class="mycode_color"><span style="font-size: x-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Descarga</span></span></span><br />
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Directo</span></span><br />
<a href="http://Registrate%20o%20inicia%20tu%20sesión%20para%20ver%20este%20contenido" target="_blank" rel="noopener" class="mycode_url">Registrate o inicia tu sesión para ver este contenido Nova UI.7z</a><br />
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Mediafire</span></span><br />
<a href="http://Registrate%20o%20inicia%20tu%20sesión%20para%20ver%20este%20contenido" target="_blank" rel="noopener" class="mycode_url">Mediafire</a><br />
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Google Drive</span></span><br />
<a href="http://Registrate%20o%20inicia%20tu%20sesión%20para%20ver%20este%20contenido" target="_blank" rel="noopener" class="mycode_url">Google Drive</a><br />
<br />
<br />
<br />
<br />
<span style="font-size: large;" class="mycode_size">Si encuentras algún error o tienes alguna sugerencia, coméntalo en este mismo hilo.</span>]]></description>
			<content:encoded><![CDATA[<div style="text-align: center;" class="mycode_align"><span style="color: #2980b9;" class="mycode_color"><span style="font-size: x-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Risus Nova UI 1.0</span></span></span></div>
<div style="text-align: center;" class="mycode_align"><span style="font-size: large;" class="mycode_size">Rediseño completo de la interfaz de Risus Nova, basado en CoreUI (Bootstrap 5), con modo oscuro incluido.</span></div>
<br />
<br />
<span style="font-weight: bold;" class="mycode_b"><span style="color: #2980b9;" class="mycode_color"><span style="font-size: x-large;" class="mycode_size">DEMO</span></span></span><br />
<a href="http://Registrate%20o%20inicia%20tu%20sesión%20para%20ver%20este%20contenido" target="_blank" rel="noopener" class="mycode_url">http://Registrate o inicia tu sesión par... contenido</a><br />
<br />
<br />
<span style="color: #2980b9;" class="mycode_color"><span style="font-size: x-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Capturas</span></span></span><br />
 <br />
<div style="text-align: center;" class="mycode_align"><img src="https://i.imgur.com/ecLwmLn.png" loading="lazy"  alt="[Imagen: ecLwmLn.png]" class="mycode_img img-responsive" /></div>
<div style="text-align: center;" class="mycode_align"><img src="https://i.imgur.com/CUpxLBC.png" loading="lazy"  alt="[Imagen: CUpxLBC.png]" class="mycode_img img-responsive" /></div>
<div style="text-align: center;" class="mycode_align"><img src="https://i.imgur.com/4m0X0Xp.png" loading="lazy"  alt="[Imagen: 4m0X0Xp.png]" class="mycode_img img-responsive" /></div>
<div style="text-align: center;" class="mycode_align"><img src="https://i.imgur.com/UYTV5qI.png" loading="lazy"  alt="[Imagen: UYTV5qI.png]" class="mycode_img img-responsive" /></div>
<div style="text-align: center;" class="mycode_align"><img src="https://i.imgur.com/v84x7Gl.png" loading="lazy"  alt="[Imagen: v84x7Gl.png]" class="mycode_img img-responsive" /></div>
<br />
<br />
<br />
<span style="font-size: x-large;" class="mycode_size"><span style="color: #2980b9;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">¿Qué incluye?</span></span></span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size">Rediseño completo con CoreUI (Bootstrap 5) en lugar de la maquetación clásica.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Modo claro / oscuro / automático (según el sistema).</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Iconos de CoreUI Icons Free en la barra lateral.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Compatible con Risus Nova 2.1.5.</span><br />
</li>
</ul>
<br />
<br />
<br />
<span style="color: #2980b9;" class="mycode_color"><span style="font-size: x-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Descarga</span></span></span><br />
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Directo</span></span><br />
<a href="http://Registrate%20o%20inicia%20tu%20sesión%20para%20ver%20este%20contenido" target="_blank" rel="noopener" class="mycode_url">Registrate o inicia tu sesión para ver este contenido Nova UI.7z</a><br />
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Mediafire</span></span><br />
<a href="http://Registrate%20o%20inicia%20tu%20sesión%20para%20ver%20este%20contenido" target="_blank" rel="noopener" class="mycode_url">Mediafire</a><br />
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Google Drive</span></span><br />
<a href="http://Registrate%20o%20inicia%20tu%20sesión%20para%20ver%20este%20contenido" target="_blank" rel="noopener" class="mycode_url">Google Drive</a><br />
<br />
<br />
<br />
<br />
<span style="font-size: large;" class="mycode_size">Si encuentras algún error o tienes alguna sugerencia, coméntalo en este mismo hilo.</span>]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[Problemas detectados durante la instalación y solución encontrada]]></title>
			<link>https://phpost.es/tema-RESUELTO-Problemas-detectados-durante-la-instalaci%C3%B3n-y-soluci%C3%B3n-encontrada</link>
			<pubDate>Sun, 19 Jul 2026 13:11:21 +0200</pubDate>
			<dc:creator><![CDATA[<a href="https://phpost.es/member.php?action=profile&uid=239">xsxTHORxsx</a>]]></dc:creator>
			<guid isPermaLink="false">https://phpost.es/tema-RESUELTO-Problemas-detectados-durante-la-instalaci%C3%B3n-y-soluci%C3%B3n-encontrada</guid>
			<description><![CDATA[<span style="font-size: x-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Problemas detectados durante la instalación y solución encontrada</span></span><br />
<br />
Durante la instalación del sistema detecté varios problemas que impedían completar correctamente el proceso, incluso utilizando una base de datos completamente nueva.<br />
<br />
Después de analizar el instalador, revisar el código PHP y realizar múltiples pruebas, logré identificar la causa principal de los errores.<br />
<hr class="mycode_hr" />
<br />
=16<span style="font-weight: bold;" class="mycode_b">Problemas encontrados</span><br />
 <ul class="mycode_list"><li>La instalación terminaba indicando:<br />
 <div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>⚠ La instalación quedó incompleta: se detectaron 18 errores.</code></div></div><br />
</li>
<li>El sistema creaba el archivo <span style="font-weight: bold;" class="mycode_b">install.lock</span> incluso cuando la instalación había fallado.<br />
<br />
</li>
<li>Al volver a ingresar al instalador aparecía un error 403 porque el propio instalador se bloqueaba.<br />
<br />
</li>
<li>El usuario debía eliminar manualmente el archivo install.lock para volver a intentarlo.<br />
<br />
</li>
<li>El instalador contabilizaba como errores situaciones que realmente eran advertencias normales de MySQL/MariaDB.<br />
</li>
</ul>
 <br />
<hr class="mycode_hr" />
<br />
=16<span style="font-weight: bold;" class="mycode_b">Análisis realizado</span><br />
<br />
Se revisó completamente el proceso de instalación.<br />
<br />
El problema no estaba relacionado con:<br />
 <ul class="mycode_list"><li>PHP<br />
</li>
<li>Permisos del servidor<br />
</li>
<li>config.inc.php<br />
</li>
<li>Conexión a MySQL<br />
</li>
<li>Versión de MariaDB<br />
</li>
</ul>
<br />
Después de revisar el archivo responsable de crear la base de datos se detectó un problema lógico.<br />
<hr class="mycode_hr" />
<br />
=16<span style="font-weight: bold;" class="mycode_b">Causa real del problema</span><br />
<br />
El instalador ejecutaba consultas similares a las siguientes:<br />
 <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>CREATE TABLE usuarios (...)<br />
ALTER TABLE usuarios ADD COLUMN avatar ...<br />
ALTER TABLE usuarios ADD COLUMN rango ...<br />
ALTER TABLE usuarios ADD COLUMN estado ...</code></div></div><br />
Sin embargo, muchas de esas columnas ya habían sido creadas anteriormente dentro del propio CREATE TABLE.<br />
<br />
Posteriormente el instalador volvía a ejecutar:<br />
 <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>ALTER TABLE ADD COLUMN ...</code></div></div><br />
MariaDB respondía correctamente con mensajes como:<br />
 <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>Duplicate column name<br />
Duplicate key name<br />
Table already exists<br />
Duplicate entry</code></div></div><br />
Estos mensajes no representan necesariamente un fallo crítico.<br />
<br />
Simplemente indican que el elemento ya existe.<br />
<br />
El problema era que el instalador contabilizaba cada uno de esos mensajes como un error fatal.<br />
<br />
Por eso aparecía finalmente:<br />
 <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>18 errores encontrados</code></div></div><br />
cuando en realidad gran parte de ellos correspondían a elementos ya existentes.<br />
<hr class="mycode_hr" />
<br />
=16<span style="font-weight: bold;" class="mycode_b">Segundo problema detectado</span><br />
<br />
Al finalizar la instalación el sistema ejecutaba inmediatamente:<br />
 <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>touch("install.lock");</code></div></div><br />
o su equivalente.<br />
<br />
Luego mostraba la pantalla final.<br />
<br />
Si existía cualquier advertencia durante el proceso, el instalador ya había quedado bloqueado.<br />
<br />
Eso provocaba:<br />
 <ul class="mycode_list"><li>Error 403<br />
</li>
<li>Instalación incompleta<br />
</li>
<li>Imposibilidad de continuar<br />
</li>
</ul>
 <br />
<hr class="mycode_hr" />
<br />
=16<span style="font-weight: bold;" class="mycode_b">Otros problemas encontrados</span><br />
 <ul class="mycode_list"><li>No se verificaba correctamente si config.inc.php realmente se había escrito.<br />
<br />
</li>
<li>No existía validación adecuada para mysqli.<br />
<br />
</li>
<li>La conexión podía fallar sin informar el motivo exacto.<br />
<br />
</li>
<li>El puerto MySQL no siempre era considerado.<br />
<br />
</li>
<li>No existía tolerancia para instalaciones parcialmente ejecutadas.<br />
<br />
</li>
<li>No se comprobaba correctamente la escritura del archivo install.lock.<br />
<br />
</li>
<li>La instalación no era completamente repetible.<br />
</li>
</ul>
 <br />
<hr class="mycode_hr" />
<br />
=16<span style="font-weight: bold;" class="mycode_b">Solución aplicada</span><br />
<br />
Se modificó el instalador para que:<br />
 <ul class="mycode_list"><li>No considere como errores los elementos que ya existen.<br />
<br />
</li>
<li>Detecte previamente tablas.<br />
<br />
</li>
<li>Detecte columnas existentes.<br />
<br />
</li>
<li>Detecte índices existentes.<br />
<br />
</li>
<li>Detecte registros duplicados.<br />
<br />
</li>
<li>Solo cree install.lock cuando toda la instalación finalice correctamente.<br />
<br />
</li>
<li>Permita repetir una instalación fallida sin bloquear el sistema.<br />
<br />
</li>
<li>Mejore el manejo de errores de MySQL y MariaDB.<br />
<br />
</li>
<li>Valide correctamente la escritura de config.inc.php.<br />
<br />
</li>
<li>Sea compatible con versiones actuales de PHP y MariaDB.<br />
</li>
</ul>
 <br />
<hr class="mycode_hr" />
<br />
=16<span style="font-weight: bold;" class="mycode_b">Resultado obtenido</span><br />
<br />
Después de aplicar las correcciones:<br />
 <ul class="mycode_list"><li>La instalación puede repetirse sin errores.<br />
<br />
</li>
<li>No se generan falsos positivos.<br />
<br />
</li>
<li>El sistema no se bloquea prematuramente.<br />
<br />
</li>
<li>Los errores reales se distinguen claramente de simples advertencias.<br />
<br />
</li>
<li>La experiencia de instalación es considerablemente más estable.<br />
</li>
</ul>
 <br />
<hr class="mycode_hr" />
<br />
=16<span style="font-weight: bold;" class="mycode_b">Recomendaciones para futuras versiones</span><br />
 <ul class="mycode_list"><li>Utilizar migraciones versionadas en lugar de múltiples ALTER TABLE.<br />
<br />
</li>
<li>Implementar comprobaciones mediante INFORMATION_SCHEMA antes de modificar tablas.<br />
<br />
</li>
<li>Registrar todos los errores en un archivo install.log.<br />
<br />
</li>
<li>Mostrar al usuario exactamente qué consulta SQL falló.<br />
<br />
</li>
<li>Separar advertencias de errores críticos.<br />
<br />
</li>
<li>Incorporar un modo de reparación ("Repair Installation") para instalaciones incompletas.<br />
<br />
</li>
<li>Permitir actualizar instalaciones existentes sin generar errores por objetos previamente creados.<br />
</li>
</ul>
 <br />
<hr class="mycode_hr" />
<br />
=16<span style="font-weight: bold;" class="mycode_b">Conclusión</span><br />
<br />
El origen del problema no estaba en el servidor, en PHP ni en MariaDB.<br />
<br />
La causa principal correspondía a la lógica del instalador, que interpretaba como errores críticos respuestas normales del motor de base de datos al intentar crear nuevamente tablas, columnas e índices ya existentes.<br />
<br />
Corrigiendo esa lógica y retrasando la creación del archivo de bloqueo hasta el final del proceso, el instalador se vuelve mucho más robusto, repetible y compatible con diferentes entornos de alojamiento.]]></description>
			<content:encoded><![CDATA[<span style="font-size: x-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Problemas detectados durante la instalación y solución encontrada</span></span><br />
<br />
Durante la instalación del sistema detecté varios problemas que impedían completar correctamente el proceso, incluso utilizando una base de datos completamente nueva.<br />
<br />
Después de analizar el instalador, revisar el código PHP y realizar múltiples pruebas, logré identificar la causa principal de los errores.<br />
<hr class="mycode_hr" />
<br />
=16<span style="font-weight: bold;" class="mycode_b">Problemas encontrados</span><br />
 <ul class="mycode_list"><li>La instalación terminaba indicando:<br />
 <div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>⚠ La instalación quedó incompleta: se detectaron 18 errores.</code></div></div><br />
</li>
<li>El sistema creaba el archivo <span style="font-weight: bold;" class="mycode_b">install.lock</span> incluso cuando la instalación había fallado.<br />
<br />
</li>
<li>Al volver a ingresar al instalador aparecía un error 403 porque el propio instalador se bloqueaba.<br />
<br />
</li>
<li>El usuario debía eliminar manualmente el archivo install.lock para volver a intentarlo.<br />
<br />
</li>
<li>El instalador contabilizaba como errores situaciones que realmente eran advertencias normales de MySQL/MariaDB.<br />
</li>
</ul>
 <br />
<hr class="mycode_hr" />
<br />
=16<span style="font-weight: bold;" class="mycode_b">Análisis realizado</span><br />
<br />
Se revisó completamente el proceso de instalación.<br />
<br />
El problema no estaba relacionado con:<br />
 <ul class="mycode_list"><li>PHP<br />
</li>
<li>Permisos del servidor<br />
</li>
<li>config.inc.php<br />
</li>
<li>Conexión a MySQL<br />
</li>
<li>Versión de MariaDB<br />
</li>
</ul>
<br />
Después de revisar el archivo responsable de crear la base de datos se detectó un problema lógico.<br />
<hr class="mycode_hr" />
<br />
=16<span style="font-weight: bold;" class="mycode_b">Causa real del problema</span><br />
<br />
El instalador ejecutaba consultas similares a las siguientes:<br />
 <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>CREATE TABLE usuarios (...)<br />
ALTER TABLE usuarios ADD COLUMN avatar ...<br />
ALTER TABLE usuarios ADD COLUMN rango ...<br />
ALTER TABLE usuarios ADD COLUMN estado ...</code></div></div><br />
Sin embargo, muchas de esas columnas ya habían sido creadas anteriormente dentro del propio CREATE TABLE.<br />
<br />
Posteriormente el instalador volvía a ejecutar:<br />
 <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>ALTER TABLE ADD COLUMN ...</code></div></div><br />
MariaDB respondía correctamente con mensajes como:<br />
 <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>Duplicate column name<br />
Duplicate key name<br />
Table already exists<br />
Duplicate entry</code></div></div><br />
Estos mensajes no representan necesariamente un fallo crítico.<br />
<br />
Simplemente indican que el elemento ya existe.<br />
<br />
El problema era que el instalador contabilizaba cada uno de esos mensajes como un error fatal.<br />
<br />
Por eso aparecía finalmente:<br />
 <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>18 errores encontrados</code></div></div><br />
cuando en realidad gran parte de ellos correspondían a elementos ya existentes.<br />
<hr class="mycode_hr" />
<br />
=16<span style="font-weight: bold;" class="mycode_b">Segundo problema detectado</span><br />
<br />
Al finalizar la instalación el sistema ejecutaba inmediatamente:<br />
 <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>touch("install.lock");</code></div></div><br />
o su equivalente.<br />
<br />
Luego mostraba la pantalla final.<br />
<br />
Si existía cualquier advertencia durante el proceso, el instalador ya había quedado bloqueado.<br />
<br />
Eso provocaba:<br />
 <ul class="mycode_list"><li>Error 403<br />
</li>
<li>Instalación incompleta<br />
</li>
<li>Imposibilidad de continuar<br />
</li>
</ul>
 <br />
<hr class="mycode_hr" />
<br />
=16<span style="font-weight: bold;" class="mycode_b">Otros problemas encontrados</span><br />
 <ul class="mycode_list"><li>No se verificaba correctamente si config.inc.php realmente se había escrito.<br />
<br />
</li>
<li>No existía validación adecuada para mysqli.<br />
<br />
</li>
<li>La conexión podía fallar sin informar el motivo exacto.<br />
<br />
</li>
<li>El puerto MySQL no siempre era considerado.<br />
<br />
</li>
<li>No existía tolerancia para instalaciones parcialmente ejecutadas.<br />
<br />
</li>
<li>No se comprobaba correctamente la escritura del archivo install.lock.<br />
<br />
</li>
<li>La instalación no era completamente repetible.<br />
</li>
</ul>
 <br />
<hr class="mycode_hr" />
<br />
=16<span style="font-weight: bold;" class="mycode_b">Solución aplicada</span><br />
<br />
Se modificó el instalador para que:<br />
 <ul class="mycode_list"><li>No considere como errores los elementos que ya existen.<br />
<br />
</li>
<li>Detecte previamente tablas.<br />
<br />
</li>
<li>Detecte columnas existentes.<br />
<br />
</li>
<li>Detecte índices existentes.<br />
<br />
</li>
<li>Detecte registros duplicados.<br />
<br />
</li>
<li>Solo cree install.lock cuando toda la instalación finalice correctamente.<br />
<br />
</li>
<li>Permita repetir una instalación fallida sin bloquear el sistema.<br />
<br />
</li>
<li>Mejore el manejo de errores de MySQL y MariaDB.<br />
<br />
</li>
<li>Valide correctamente la escritura de config.inc.php.<br />
<br />
</li>
<li>Sea compatible con versiones actuales de PHP y MariaDB.<br />
</li>
</ul>
 <br />
<hr class="mycode_hr" />
<br />
=16<span style="font-weight: bold;" class="mycode_b">Resultado obtenido</span><br />
<br />
Después de aplicar las correcciones:<br />
 <ul class="mycode_list"><li>La instalación puede repetirse sin errores.<br />
<br />
</li>
<li>No se generan falsos positivos.<br />
<br />
</li>
<li>El sistema no se bloquea prematuramente.<br />
<br />
</li>
<li>Los errores reales se distinguen claramente de simples advertencias.<br />
<br />
</li>
<li>La experiencia de instalación es considerablemente más estable.<br />
</li>
</ul>
 <br />
<hr class="mycode_hr" />
<br />
=16<span style="font-weight: bold;" class="mycode_b">Recomendaciones para futuras versiones</span><br />
 <ul class="mycode_list"><li>Utilizar migraciones versionadas en lugar de múltiples ALTER TABLE.<br />
<br />
</li>
<li>Implementar comprobaciones mediante INFORMATION_SCHEMA antes de modificar tablas.<br />
<br />
</li>
<li>Registrar todos los errores en un archivo install.log.<br />
<br />
</li>
<li>Mostrar al usuario exactamente qué consulta SQL falló.<br />
<br />
</li>
<li>Separar advertencias de errores críticos.<br />
<br />
</li>
<li>Incorporar un modo de reparación ("Repair Installation") para instalaciones incompletas.<br />
<br />
</li>
<li>Permitir actualizar instalaciones existentes sin generar errores por objetos previamente creados.<br />
</li>
</ul>
 <br />
<hr class="mycode_hr" />
<br />
=16<span style="font-weight: bold;" class="mycode_b">Conclusión</span><br />
<br />
El origen del problema no estaba en el servidor, en PHP ni en MariaDB.<br />
<br />
La causa principal correspondía a la lógica del instalador, que interpretaba como errores críticos respuestas normales del motor de base de datos al intentar crear nuevamente tablas, columnas e índices ya existentes.<br />
<br />
Corrigiendo esa lógica y retrasando la creación del archivo de bloqueo hasta el final del proceso, el instalador se vuelve mucho más robusto, repetible y compatible con diferentes entornos de alojamiento.]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[PHPost v3.9.8 - La nueva etapa del proyecto]]></title>
			<link>https://phpost.es/tema-NOTICIAS-NO-OFICIAL-PHPost-v3-9-8-La-nueva-etapa-del-proyecto</link>
			<pubDate>Fri, 17 Jul 2026 05:38:03 +0200</pubDate>
			<dc:creator><![CDATA[<a href="https://phpost.es/member.php?action=profile&uid=23">Miguel92</a>]]></dc:creator>
			<guid isPermaLink="false">https://phpost.es/tema-NOTICIAS-NO-OFICIAL-PHPost-v3-9-8-La-nueva-etapa-del-proyecto</guid>
			<description><![CDATA[Hace tiempo que vengo trabajando en <span style="font-weight: bold;" class="mycode_b">PHPost</span> de forma incremental, parcheando aquí y allá, añadiendo funcionalidades sin mirar demasiado atrás. Pero llegó el momento de parar y hacer bien las cosas. No se trata solo de refactorizar: es una modernización completa del proyecto, de <span style="font-weight: bold;" class="mycode_b">PHP 7.4/8.0</span> a <span style="font-weight: bold;" class="mycode_b">PHP 8.3/8.4/8.5</span>, con todo lo que eso implica.<br />
<br />
<span style="font-style: italic;" class="mycode_i"><span style="text-decoration: underline;" class="mycode_u">La versión actual es la <span style="font-weight: bold;" class="mycode_b">3.9.8</span>, y es donde empieza esta nueva era.</span></span><br />
<br />
<span style="text-decoration: underline;" class="mycode_u"><span style="font-weight: bold;" class="mycode_b">Vulnerabilidades corregidas:</span></span><br />
- <span style="font-weight: bold;" class="mycode_b">SQL Injection</span>: Migradas a <span style="text-decoration: underline;" class="mycode_u"><span style="font-weight: bold;" class="mycode_b">prepared statements</span></span><br />
- <span style="font-weight: bold;" class="mycode_b">CSRF</span>: validación automática en <span style="font-weight: bold;" class="mycode_b">RequestGuard</span><br />
- <span style="font-weight: bold;" class="mycode_b">XSS</span>: escape universal de HTML via <span style="font-weight: bold;" class="mycode_b">Html::escape()</span><br />
- <span style="font-weight: bold;" class="mycode_b">Sesiones</span>: IDs con 256 bits de entropía usando <span style="font-weight: bold;" class="mycode_b">bin2hex(random_bytes(32))</span><br />
- <span style="font-weight: bold;" class="mycode_b">JavaScript</span>: Migrados a helper <span style="font-weight: bold;" class="mycode_b">api()</span> centralizado con <span style="font-weight: bold;" class="mycode_b">headers CSRF</span> automáticos<br />
<br />
<span style="font-weight: bold;" class="mycode_b">¿Qué se está haciendo ahora?</span><br />
El foco está en tres grandes áreas:<br />
<br />
<span style="font-size: medium;" class="mycode_size"><span style="text-decoration: underline;" class="mycode_u">1. Capa de base de datos completamente nueva</span></span><br />
El viejo <span style="font-weight: bold;" class="mycode_b">db_exec()</span> y <span style="font-weight: bold;" class="mycode_b">result_array()</span> quedaron atrás.<br />
Ahora tenemos:<br />
- Clase Database con <span style="font-weight: bold;" class="mycode_b">mysqli</span>, <span style="font-weight: bold;" class="mycode_b">soporte SSL</span>, <span style="font-weight: bold;" class="mycode_b">prepared statements</span> nombrados (:param), transacciones y manejo de excepciones. (posiblemente lo migre a <span style="font-weight: bold;" class="mycode_b">PDO</span>, seguirá funcionando igual)<br />
- Fachada DB con métodos estáticos: <span style="font-weight: bold;" class="mycode_b">DB::fetch()</span>, <span style="font-weight: bold;" class="mycode_b">DB::insert()</span>, <span style="font-weight: bold;" class="mycode_b">DB::update()</span>, <span style="font-weight: bold;" class="mycode_b">DB::delete()</span>, <span style="font-weight: bold;" class="mycode_b">DB::upsert()</span>, <span style="font-weight: bold;" class="mycode_b">DB::increment()</span>, <span style="font-weight: bold;" class="mycode_b">DB::exists()</span>, <span style="font-weight: bold;" class="mycode_b">DB::value()</span>, <span style="font-weight: bold;" class="mycode_b">DB::column()</span><br />
<br />
<span style="font-size: medium;" class="mycode_size"><span style="text-decoration: underline;" class="mycode_u">2. Sistema de seguridad desde cero</span></span><br />
Se crearon componentes nuevos para cubrir vulnerabilidades:<br />
- <span style="font-weight: bold;" class="mycode_b">RequestGuard</span> - <span style="font-style: italic;" class="mycode_i">valida cada petición</span>: rechaza inyección de <span style="font-weight: bold;" class="mycode_b">globals</span>, <span style="font-weight: bold;" class="mycode_b">claves inválidas</span>, <span style="font-weight: bold;" class="mycode_b">payloads oversized</span>, y <span style="font-weight: bold;" class="mycode_b">valida CSRF</span> automáticamente <span style="font-style: italic;" class="mycode_i">(antiguamente era QueryString.php, pero no hace exactamente lo mismo)</span><br />
- <span style="font-weight: bold;" class="mycode_b">CsrfToken</span> - generación y validación de tokens <span style="font-weight: bold;" class="mycode_b">CSRF</span> con <span style="font-weight: bold;" class="mycode_b">random_bytes()</span> y <span style="font-weight: bold;" class="mycode_b">hash_equals()</span><br />
- <span style="font-weight: bold;" class="mycode_b">Password</span> - hashing moderno con <span style="font-weight: bold;" class="mycode_b">Argon2id/Bcrypt</span>, validación de fortaleza, bloqueo de contraseñas comunes, cálculo de entropía, historial y expiración<br />
- <span style="font-weight: bold;" class="mycode_b">IP</span> - detección segura de IP con soporte de proxies de confianza<br />
- <span style="font-weight: bold;" class="mycode_b">Html</span> - escape centralizado de HTML con <span style="font-weight: bold;" class="mycode_b">Html::escape()</span>, reemplazando la vieja <span style="font-weight: bold;" class="mycode_b">setSecure()</span><br />
- <span style="font-weight: bold;" class="mycode_b">Response</span> - respuestas HTTP con <span style="font-weight: bold;" class="mycode_b">headers CSP nonce</span>, <span style="font-weight: bold;" class="mycode_b">JSON/HTML/Text</span>, descargas y redirecciones<br />
<br />
<span style="font-size: medium;" class="mycode_size"><span style="text-decoration: underline;" class="mycode_u">3. Infraestructura moderna</span></span><br />
- Contenedor de inyección de dependencias (Container) con <span style="font-weight: bold;" class="mycode_b">autowiring</span>, <span style="font-weight: bold;" class="mycode_b">singleton</span>, <span style="font-weight: bold;" class="mycode_b">factory </span>y <span style="font-weight: bold;" class="mycode_b">bindings</span><br />
- Sistema de rutas con notación de puntos y dos puntos, generación de URLs y resolución de rutas. <span style="font-style: italic;" class="mycode_i">(ej: &#36;Route-&gt;get('assets.css') o &#36;Route-&gt;get('assets:css'), para simplificar)</span><br />
- Sistema de <span style="font-weight: bold;" class="mycode_b">hooks</span> con prioridades, integrado con Smarty para inyección de contenido, <span style="font-weight: bold;" class="mycode_b">a penas iniciado</span>. (tengo que integrarlo a los themes aun, pero funciona)<br />
- <span style="font-weight: bold;" class="mycode_b">Logger</span> con <span style="font-weight: bold;" class="mycode_b">LogLevel</span> como <span style="text-decoration: underline;" class="mycode_u"><span style="font-weight: bold;" class="mycode_b">enum de PHP 8.1+</span></span>, formateo estructurado y archivos por canal con fecha<br />
- Capa de compatibilidad <span style="font-weight: bold;" class="mycode_b">PHP 8.5</span> para manejar deprecaciones como <span style="font-weight: bold;" class="mycode_b">curl_close()</span>, <span style="font-weight: bold;" class="mycode_b">imagedestroy()</span>, <span style="font-weight: bold;" class="mycode_b">finfo_close()</span><br />
- Sistema de configuración con lazy loading: <span style="font-weight: bold;" class="mycode_b">Config::app()</span>, <span style="font-weight: bold;" class="mycode_b">Config::db()</span>, <span style="font-weight: bold;" class="mycode_b">Config::mail()</span><br />
- ThemeManifest para parsear archivos <span style="font-weight: bold;" class="mycode_b">info.theme</span> con metadata de themes<br />
- Sistema de ImageProviders con estrategia intercambiable: <span style="font-weight: bold;" class="mycode_b">Cloudinary</span>, <span style="font-weight: bold;" class="mycode_b">ImgBB</span>, <span style="font-weight: bold;" class="mycode_b">Imgur</span><br />
- Sistema de emails con API fluida: <span style="font-weight: bold;" class="mycode_b">&#36;email-&gt;to()-&gt;subject()-&gt;body()-&gt;send()</span><br />
- Migraciones de base de datos con tracking en tabla <span style="font-weight: bold;" class="mycode_b">w_migrations</span><br />
<br />
<span style="font-size: medium;" class="mycode_size"><span style="text-decoration: underline;" class="mycode_u">4. Frontend</span></span><br />
- Helper <span style="font-weight: bold;" class="mycode_b">centralizado api() con headers CSRF</span> automáticos, parseo JSON, manejo de errores y timeouts<br />
- Sistema de dialog con init(), alert(), loading(), toast(), reintentar() (es el modal, pero modificado y "plugin")<br />
- Lazy loading con <span style="font-weight: bold;" class="mycode_b">IntersectionObserver</span> para imágenes y elementos picture<br />
- Integración de <span style="font-weight: bold;" class="mycode_b">Highlight.js</span> para bloques de código en BBCode<br />
<br />
<span style="font-size: medium;" class="mycode_size"><span style="text-decoration: underline;" class="mycode_u">5. Tipado completo</span></span><br />
Más de 2,000 funciones con tipos de retorno y parámetros aplicados en archivos:<br />
- Tipos usados: <span style="font-weight: bold;" class="mycode_b">array</span>, <span style="font-weight: bold;" class="mycode_b">?array</span>, <span style="font-weight: bold;" class="mycode_b">string</span>, <span style="font-weight: bold;" class="mycode_b">bool</span>, <span style="font-weight: bold;" class="mycode_b">void</span>, <span style="font-weight: bold;" class="mycode_b">string|bool</span>, <span style="font-weight: bold;" class="mycode_b">never</span>, <span style="font-weight: bold;" class="mycode_b">mixed</span>, <span style="font-weight: bold;" class="mycode_b">int</span>, <span style="font-weight: bold;" class="mycode_b">float</span>, <span style="font-weight: bold;" class="mycode_b">etc</span>.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">¿Qué queda pendiente?</span><br />
- <span style="font-weight: bold;" class="mycode_b">3 vulnerabilidades críticas</span>: eval() en el sistema de <span style="font-weight: bold;" class="mycode_b">dialog.js</span>, open redirect en <span style="font-weight: bold;" class="mycode_b">login.js</span>, <span style="text-decoration: underline;" class="mycode_u">stored XSS</span> en <span style="font-weight: bold;" class="mycode_b">perfil.js</span><br />
- <span style="font-weight: bold;" class="mycode_b">2 problemas medios</span>: inconsistencia de cookies <span style="font-weight: bold;" class="mycode_b">SameSite</span>, <span style="font-weight: bold;" class="mycode_b">unserialize()</span> en Container<br />
- <span style="font-weight: bold;" class="mycode_b">12 problemas bajos</span>: migración <span style="font-weight: bold;" class="mycode_b">switch-to-match</span>, propiedades <span style="font-weight: bold;" class="mycode_b">readonly</span>, evaluación de dependencia jQuery, accesibilidad (<span style="font-weight: bold;" class="mycode_b">ARIA</span>,<span style="font-weight: bold;" class="mycode_b"> focus traps</span>), expansión de CSP nonces<br />
<br />
<span style="font-size: medium;" class="mycode_size"><span style="text-decoration: underline;" class="mycode_u">Compatibilidad</span></span><br />
No habrá compatibilidad hacia atrás. Los cambios en la base de datos y la estructura del código romperán con versiones anteriores. Esto es necesario para avanzar.<br />
<br />
<span style="font-size: medium;" class="mycode_size"><span style="text-decoration: underline;" class="mycode_u">Estabilidad</span></span><br />
Durante la transición puede haber inestabilidad temporal y algunas funcionalidades deshabilitadas temporalmente.<br />
<br />
<span style="font-size: large;" class="mycode_size">El objetivo</span><br />
<span style="text-decoration: underline;" class="mycode_u"><span style="font-size: medium;" class="mycode_size">Un proyecto que sea:</span></span><br />
✅ <span style="font-weight: bold;" class="mycode_b">Más comprensible</span> - código claro que cualquiera pueda entender<br />
✅ <span style="font-weight: bold;" class="mycode_b">Más simple</span> - sin complejidad innecesaria ni código oscuro<br />
✅ <span style="font-weight: bold;" class="mycode_b">Más mantenible</span> - fácil de actualizar y extender<br />
✅ <span style="font-weight: bold;" class="mycode_b">Más robusto</span> - menos bugs, mejor manejo de errores<br />
✅ <span style="font-weight: bold;" class="mycode_b">Más moderno</span> - aprovechando <span style="font-weight: bold;" class="mycode_b">PHP 8.5</span> y las mejores prácticas actuales<br />
✅ <span style="text-decoration: line-through;" class="mycode_s"><span style="font-weight: bold;" class="mycode_b">Mejor documentado</span> - para que otros puedan contribuir </span>Aun no lo hice<br />
<br />
<span style="font-size: medium;" class="mycode_size"><span style="text-decoration: underline;" class="mycode_u">Si quieres contribuir:</span></span><br />
- Espera a que la nueva estructura esté lista<br />
- Revisa la documentación cuando esté disponible<br />
- Reporta issues si encuentras algo en las versiones de desarrollo<br />
- Ideas siempre son bienvenidas, no hace falta contribuir con código<br />
<br />
<span style="font-size: medium;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Reflexión final</span></span><br />
Sé que romper compatibilidad nunca es fácil, pero a veces es necesario para avanzar. He aprendido mucho con este proyecto, y parte de ese aprendizaje es reconocer cuándo algo necesita ser rehecho correctamente en lugar de seguir parcheando. Este es un compromiso con la calidad a largo plazo.<br />
<br />
Última versión estable: <a href="http://Registrate%20o%20inicia%20tu%20sesión%20para%20ver%20este%20contenido" target="_blank" rel="noopener" class="mycode_url">http://Registrate o inicia tu sesión par... contenido</a> (creo que podría ser este, es del 2022)<br />
Última versión anterior estable: <a href="http://Registrate%20o%20inicia%20tu%20sesión%20para%20ver%20este%20contenido" target="_blank" rel="noopener" class="mycode_url">http://Registrate o inicia tu sesión par... contenido</a> (este es del 2019 php 7)<br />
Última versión desarrollo: <a href="http://Registrate%20o%20inicia%20tu%20sesión%20para%20ver%20este%20contenido" target="_blank" rel="noopener" class="mycode_url">http://Registrate o inicia tu sesión par... contenido</a> (subido 15.04.26, no contiene las imágenes de categorías, tiene otras .svg)<br />
<br />
Si se les hace conocido el final del topic <span style="font-weight: bold;" class="mycode_b"><a href="http://Registrate%20o%20inicia%20tu%20sesión%20para%20ver%20este%20contenido" target="_blank" rel="noopener" class="mycode_url">lo tome de mi otro topic</a></span> hecho.<br />
Para descargarlo, lo encontrarán en [b][url=Registrate o inicia tu sesión para ver este contenido]el servidor de ***** #descarga-test]]></description>
			<content:encoded><![CDATA[Hace tiempo que vengo trabajando en <span style="font-weight: bold;" class="mycode_b">PHPost</span> de forma incremental, parcheando aquí y allá, añadiendo funcionalidades sin mirar demasiado atrás. Pero llegó el momento de parar y hacer bien las cosas. No se trata solo de refactorizar: es una modernización completa del proyecto, de <span style="font-weight: bold;" class="mycode_b">PHP 7.4/8.0</span> a <span style="font-weight: bold;" class="mycode_b">PHP 8.3/8.4/8.5</span>, con todo lo que eso implica.<br />
<br />
<span style="font-style: italic;" class="mycode_i"><span style="text-decoration: underline;" class="mycode_u">La versión actual es la <span style="font-weight: bold;" class="mycode_b">3.9.8</span>, y es donde empieza esta nueva era.</span></span><br />
<br />
<span style="text-decoration: underline;" class="mycode_u"><span style="font-weight: bold;" class="mycode_b">Vulnerabilidades corregidas:</span></span><br />
- <span style="font-weight: bold;" class="mycode_b">SQL Injection</span>: Migradas a <span style="text-decoration: underline;" class="mycode_u"><span style="font-weight: bold;" class="mycode_b">prepared statements</span></span><br />
- <span style="font-weight: bold;" class="mycode_b">CSRF</span>: validación automática en <span style="font-weight: bold;" class="mycode_b">RequestGuard</span><br />
- <span style="font-weight: bold;" class="mycode_b">XSS</span>: escape universal de HTML via <span style="font-weight: bold;" class="mycode_b">Html::escape()</span><br />
- <span style="font-weight: bold;" class="mycode_b">Sesiones</span>: IDs con 256 bits de entropía usando <span style="font-weight: bold;" class="mycode_b">bin2hex(random_bytes(32))</span><br />
- <span style="font-weight: bold;" class="mycode_b">JavaScript</span>: Migrados a helper <span style="font-weight: bold;" class="mycode_b">api()</span> centralizado con <span style="font-weight: bold;" class="mycode_b">headers CSRF</span> automáticos<br />
<br />
<span style="font-weight: bold;" class="mycode_b">¿Qué se está haciendo ahora?</span><br />
El foco está en tres grandes áreas:<br />
<br />
<span style="font-size: medium;" class="mycode_size"><span style="text-decoration: underline;" class="mycode_u">1. Capa de base de datos completamente nueva</span></span><br />
El viejo <span style="font-weight: bold;" class="mycode_b">db_exec()</span> y <span style="font-weight: bold;" class="mycode_b">result_array()</span> quedaron atrás.<br />
Ahora tenemos:<br />
- Clase Database con <span style="font-weight: bold;" class="mycode_b">mysqli</span>, <span style="font-weight: bold;" class="mycode_b">soporte SSL</span>, <span style="font-weight: bold;" class="mycode_b">prepared statements</span> nombrados (:param), transacciones y manejo de excepciones. (posiblemente lo migre a <span style="font-weight: bold;" class="mycode_b">PDO</span>, seguirá funcionando igual)<br />
- Fachada DB con métodos estáticos: <span style="font-weight: bold;" class="mycode_b">DB::fetch()</span>, <span style="font-weight: bold;" class="mycode_b">DB::insert()</span>, <span style="font-weight: bold;" class="mycode_b">DB::update()</span>, <span style="font-weight: bold;" class="mycode_b">DB::delete()</span>, <span style="font-weight: bold;" class="mycode_b">DB::upsert()</span>, <span style="font-weight: bold;" class="mycode_b">DB::increment()</span>, <span style="font-weight: bold;" class="mycode_b">DB::exists()</span>, <span style="font-weight: bold;" class="mycode_b">DB::value()</span>, <span style="font-weight: bold;" class="mycode_b">DB::column()</span><br />
<br />
<span style="font-size: medium;" class="mycode_size"><span style="text-decoration: underline;" class="mycode_u">2. Sistema de seguridad desde cero</span></span><br />
Se crearon componentes nuevos para cubrir vulnerabilidades:<br />
- <span style="font-weight: bold;" class="mycode_b">RequestGuard</span> - <span style="font-style: italic;" class="mycode_i">valida cada petición</span>: rechaza inyección de <span style="font-weight: bold;" class="mycode_b">globals</span>, <span style="font-weight: bold;" class="mycode_b">claves inválidas</span>, <span style="font-weight: bold;" class="mycode_b">payloads oversized</span>, y <span style="font-weight: bold;" class="mycode_b">valida CSRF</span> automáticamente <span style="font-style: italic;" class="mycode_i">(antiguamente era QueryString.php, pero no hace exactamente lo mismo)</span><br />
- <span style="font-weight: bold;" class="mycode_b">CsrfToken</span> - generación y validación de tokens <span style="font-weight: bold;" class="mycode_b">CSRF</span> con <span style="font-weight: bold;" class="mycode_b">random_bytes()</span> y <span style="font-weight: bold;" class="mycode_b">hash_equals()</span><br />
- <span style="font-weight: bold;" class="mycode_b">Password</span> - hashing moderno con <span style="font-weight: bold;" class="mycode_b">Argon2id/Bcrypt</span>, validación de fortaleza, bloqueo de contraseñas comunes, cálculo de entropía, historial y expiración<br />
- <span style="font-weight: bold;" class="mycode_b">IP</span> - detección segura de IP con soporte de proxies de confianza<br />
- <span style="font-weight: bold;" class="mycode_b">Html</span> - escape centralizado de HTML con <span style="font-weight: bold;" class="mycode_b">Html::escape()</span>, reemplazando la vieja <span style="font-weight: bold;" class="mycode_b">setSecure()</span><br />
- <span style="font-weight: bold;" class="mycode_b">Response</span> - respuestas HTTP con <span style="font-weight: bold;" class="mycode_b">headers CSP nonce</span>, <span style="font-weight: bold;" class="mycode_b">JSON/HTML/Text</span>, descargas y redirecciones<br />
<br />
<span style="font-size: medium;" class="mycode_size"><span style="text-decoration: underline;" class="mycode_u">3. Infraestructura moderna</span></span><br />
- Contenedor de inyección de dependencias (Container) con <span style="font-weight: bold;" class="mycode_b">autowiring</span>, <span style="font-weight: bold;" class="mycode_b">singleton</span>, <span style="font-weight: bold;" class="mycode_b">factory </span>y <span style="font-weight: bold;" class="mycode_b">bindings</span><br />
- Sistema de rutas con notación de puntos y dos puntos, generación de URLs y resolución de rutas. <span style="font-style: italic;" class="mycode_i">(ej: &#36;Route-&gt;get('assets.css') o &#36;Route-&gt;get('assets:css'), para simplificar)</span><br />
- Sistema de <span style="font-weight: bold;" class="mycode_b">hooks</span> con prioridades, integrado con Smarty para inyección de contenido, <span style="font-weight: bold;" class="mycode_b">a penas iniciado</span>. (tengo que integrarlo a los themes aun, pero funciona)<br />
- <span style="font-weight: bold;" class="mycode_b">Logger</span> con <span style="font-weight: bold;" class="mycode_b">LogLevel</span> como <span style="text-decoration: underline;" class="mycode_u"><span style="font-weight: bold;" class="mycode_b">enum de PHP 8.1+</span></span>, formateo estructurado y archivos por canal con fecha<br />
- Capa de compatibilidad <span style="font-weight: bold;" class="mycode_b">PHP 8.5</span> para manejar deprecaciones como <span style="font-weight: bold;" class="mycode_b">curl_close()</span>, <span style="font-weight: bold;" class="mycode_b">imagedestroy()</span>, <span style="font-weight: bold;" class="mycode_b">finfo_close()</span><br />
- Sistema de configuración con lazy loading: <span style="font-weight: bold;" class="mycode_b">Config::app()</span>, <span style="font-weight: bold;" class="mycode_b">Config::db()</span>, <span style="font-weight: bold;" class="mycode_b">Config::mail()</span><br />
- ThemeManifest para parsear archivos <span style="font-weight: bold;" class="mycode_b">info.theme</span> con metadata de themes<br />
- Sistema de ImageProviders con estrategia intercambiable: <span style="font-weight: bold;" class="mycode_b">Cloudinary</span>, <span style="font-weight: bold;" class="mycode_b">ImgBB</span>, <span style="font-weight: bold;" class="mycode_b">Imgur</span><br />
- Sistema de emails con API fluida: <span style="font-weight: bold;" class="mycode_b">&#36;email-&gt;to()-&gt;subject()-&gt;body()-&gt;send()</span><br />
- Migraciones de base de datos con tracking en tabla <span style="font-weight: bold;" class="mycode_b">w_migrations</span><br />
<br />
<span style="font-size: medium;" class="mycode_size"><span style="text-decoration: underline;" class="mycode_u">4. Frontend</span></span><br />
- Helper <span style="font-weight: bold;" class="mycode_b">centralizado api() con headers CSRF</span> automáticos, parseo JSON, manejo de errores y timeouts<br />
- Sistema de dialog con init(), alert(), loading(), toast(), reintentar() (es el modal, pero modificado y "plugin")<br />
- Lazy loading con <span style="font-weight: bold;" class="mycode_b">IntersectionObserver</span> para imágenes y elementos picture<br />
- Integración de <span style="font-weight: bold;" class="mycode_b">Highlight.js</span> para bloques de código en BBCode<br />
<br />
<span style="font-size: medium;" class="mycode_size"><span style="text-decoration: underline;" class="mycode_u">5. Tipado completo</span></span><br />
Más de 2,000 funciones con tipos de retorno y parámetros aplicados en archivos:<br />
- Tipos usados: <span style="font-weight: bold;" class="mycode_b">array</span>, <span style="font-weight: bold;" class="mycode_b">?array</span>, <span style="font-weight: bold;" class="mycode_b">string</span>, <span style="font-weight: bold;" class="mycode_b">bool</span>, <span style="font-weight: bold;" class="mycode_b">void</span>, <span style="font-weight: bold;" class="mycode_b">string|bool</span>, <span style="font-weight: bold;" class="mycode_b">never</span>, <span style="font-weight: bold;" class="mycode_b">mixed</span>, <span style="font-weight: bold;" class="mycode_b">int</span>, <span style="font-weight: bold;" class="mycode_b">float</span>, <span style="font-weight: bold;" class="mycode_b">etc</span>.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">¿Qué queda pendiente?</span><br />
- <span style="font-weight: bold;" class="mycode_b">3 vulnerabilidades críticas</span>: eval() en el sistema de <span style="font-weight: bold;" class="mycode_b">dialog.js</span>, open redirect en <span style="font-weight: bold;" class="mycode_b">login.js</span>, <span style="text-decoration: underline;" class="mycode_u">stored XSS</span> en <span style="font-weight: bold;" class="mycode_b">perfil.js</span><br />
- <span style="font-weight: bold;" class="mycode_b">2 problemas medios</span>: inconsistencia de cookies <span style="font-weight: bold;" class="mycode_b">SameSite</span>, <span style="font-weight: bold;" class="mycode_b">unserialize()</span> en Container<br />
- <span style="font-weight: bold;" class="mycode_b">12 problemas bajos</span>: migración <span style="font-weight: bold;" class="mycode_b">switch-to-match</span>, propiedades <span style="font-weight: bold;" class="mycode_b">readonly</span>, evaluación de dependencia jQuery, accesibilidad (<span style="font-weight: bold;" class="mycode_b">ARIA</span>,<span style="font-weight: bold;" class="mycode_b"> focus traps</span>), expansión de CSP nonces<br />
<br />
<span style="font-size: medium;" class="mycode_size"><span style="text-decoration: underline;" class="mycode_u">Compatibilidad</span></span><br />
No habrá compatibilidad hacia atrás. Los cambios en la base de datos y la estructura del código romperán con versiones anteriores. Esto es necesario para avanzar.<br />
<br />
<span style="font-size: medium;" class="mycode_size"><span style="text-decoration: underline;" class="mycode_u">Estabilidad</span></span><br />
Durante la transición puede haber inestabilidad temporal y algunas funcionalidades deshabilitadas temporalmente.<br />
<br />
<span style="font-size: large;" class="mycode_size">El objetivo</span><br />
<span style="text-decoration: underline;" class="mycode_u"><span style="font-size: medium;" class="mycode_size">Un proyecto que sea:</span></span><br />
✅ <span style="font-weight: bold;" class="mycode_b">Más comprensible</span> - código claro que cualquiera pueda entender<br />
✅ <span style="font-weight: bold;" class="mycode_b">Más simple</span> - sin complejidad innecesaria ni código oscuro<br />
✅ <span style="font-weight: bold;" class="mycode_b">Más mantenible</span> - fácil de actualizar y extender<br />
✅ <span style="font-weight: bold;" class="mycode_b">Más robusto</span> - menos bugs, mejor manejo de errores<br />
✅ <span style="font-weight: bold;" class="mycode_b">Más moderno</span> - aprovechando <span style="font-weight: bold;" class="mycode_b">PHP 8.5</span> y las mejores prácticas actuales<br />
✅ <span style="text-decoration: line-through;" class="mycode_s"><span style="font-weight: bold;" class="mycode_b">Mejor documentado</span> - para que otros puedan contribuir </span>Aun no lo hice<br />
<br />
<span style="font-size: medium;" class="mycode_size"><span style="text-decoration: underline;" class="mycode_u">Si quieres contribuir:</span></span><br />
- Espera a que la nueva estructura esté lista<br />
- Revisa la documentación cuando esté disponible<br />
- Reporta issues si encuentras algo en las versiones de desarrollo<br />
- Ideas siempre son bienvenidas, no hace falta contribuir con código<br />
<br />
<span style="font-size: medium;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Reflexión final</span></span><br />
Sé que romper compatibilidad nunca es fácil, pero a veces es necesario para avanzar. He aprendido mucho con este proyecto, y parte de ese aprendizaje es reconocer cuándo algo necesita ser rehecho correctamente en lugar de seguir parcheando. Este es un compromiso con la calidad a largo plazo.<br />
<br />
Última versión estable: <a href="http://Registrate%20o%20inicia%20tu%20sesión%20para%20ver%20este%20contenido" target="_blank" rel="noopener" class="mycode_url">http://Registrate o inicia tu sesión par... contenido</a> (creo que podría ser este, es del 2022)<br />
Última versión anterior estable: <a href="http://Registrate%20o%20inicia%20tu%20sesión%20para%20ver%20este%20contenido" target="_blank" rel="noopener" class="mycode_url">http://Registrate o inicia tu sesión par... contenido</a> (este es del 2019 php 7)<br />
Última versión desarrollo: <a href="http://Registrate%20o%20inicia%20tu%20sesión%20para%20ver%20este%20contenido" target="_blank" rel="noopener" class="mycode_url">http://Registrate o inicia tu sesión par... contenido</a> (subido 15.04.26, no contiene las imágenes de categorías, tiene otras .svg)<br />
<br />
Si se les hace conocido el final del topic <span style="font-weight: bold;" class="mycode_b"><a href="http://Registrate%20o%20inicia%20tu%20sesión%20para%20ver%20este%20contenido" target="_blank" rel="noopener" class="mycode_url">lo tome de mi otro topic</a></span> hecho.<br />
Para descargarlo, lo encontrarán en [b][url=Registrate o inicia tu sesión para ver este contenido]el servidor de ***** #descarga-test]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[Guía completa: PHPost (Risus Nova) con Docker desde cero]]></title>
			<link>https://phpost.es/tema-Tutorial-Gu%C3%ADa-completa-PHPost-Risus-Nova-con-Docker-desde-cero</link>
			<pubDate>Sun, 12 Jul 2026 03:25:27 +0200</pubDate>
			<dc:creator><![CDATA[<a href="https://phpost.es/member.php?action=profile&uid=110">nesticle8bit</a>]]></dc:creator>
			<guid isPermaLink="false">https://phpost.es/tema-Tutorial-Gu%C3%ADa-completa-PHPost-Risus-Nova-con-Docker-desde-cero</guid>
			<description><![CDATA[Hola!, he vuelto a la comunidad haha, hace un tiempo llevo desarollando otro script y me dió por instalar PHPost para ver como ha evolucionado y si puedo ayudar a mejorar en mis tiempos libres, como hoy que me ha entrado las ganas de instalar el script en mi server con docker y si alguno necesita un paso a paso de como hacerlo, esta es la guía definitiva, me gustaría que si hay mejoras o correcciones de typo por ejemplo, o mejoras en cuanto a docker me escriban, por ahora, nada más que decir, solamente agradecer a los desarrolladores que siguieron aquí haciendo posible esta comunidad.<br />
<br />
Guía completa: PHPost (Risus Nova) con Docker desde cero<br />
<br />
Te digo <span style="font-weight: bold;" class="mycode_b">exactamente qué archivos crear, con qué nombre, dónde guardarlos y qué escribir dentro de cada uno</span>. Copia, pega y listo.<br />
Funciona igual en Windows, Linux y Mac. No necesitas instalar PHP, ni MySQL, ni Apache: Docker lo trae todo dentro.<br />
<br />
<span style="font-weight: bold;" class="mycode_b"><span style="font-size: large;" class="mycode_size">La estructura final (esto es lo que vamos a construir)</span></span><br />
Cuando termines, tendrás esto:<br />
 <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>phpost/<br />
│<br />
├── Script/&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;← el script Risus Nova<br />
│&nbsp;&nbsp; ├── index.php<br />
│&nbsp;&nbsp; ├── config.inc.php<br />
│&nbsp;&nbsp; ├── install/<br />
│&nbsp;&nbsp; ├── files/<br />
│&nbsp;&nbsp; └── ... (todo el contenido del script)<br />
│<br />
├── docker/&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;← carpeta que TÚ creas<br />
│&nbsp;&nbsp; ├── Dockerfile<br />
│&nbsp;&nbsp; ├── php.ini<br />
│&nbsp;&nbsp; ├── vhost.conf<br />
│&nbsp;&nbsp; └── entrypoint.sh<br />
│<br />
├── docker-compose.yml&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ← archivo que TÚ creas<br />
├── .env.example&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ← archivo que TÚ creas (plantilla)<br />
├── .env&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ← copia de .env.example con tus contraseñas<br />
└── .dockerignore&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;← archivo que TÚ creas</code></div></div><br />
En total tienes que crear <span style="font-weight: bold;" class="mycode_b">7 archivos</span> (más la carpeta <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>docker/</code></div></div>). Vamos uno por uno.<br />
<br />
<span style="font-weight: bold;" class="mycode_b"><span style="font-size: large;" class="mycode_size">Paso 0: prepara la carpeta base</span></span><br />
<ol type="1" class="mycode_list"><li>Crea una carpeta para el proyecto. La llamaré <div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>phpost/</code></div></div> pero puedes ponerle el nombre que quieras.<br />
</li>
<li>Descarga Risus Nova de <a href="http://Registrate%20o%20inicia%20tu%20sesión%20para%20ver%20este%20contenido" target="_blank" rel="noopener" class="mycode_url">phpost.es</a> e <span style="font-weight: bold;" class="mycode_b">inserta todo el contenido del script dentro de una subcarpeta llamada <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>Script/</code></div></div></span>.<br />
</li>
<li>Crea una carpeta vacía llamada <div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>docker/</code></div></div> al lado de <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>Script/</code></div></div>.<br />
</li>
</ol>
Quedaría así:<br />
 <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>phpost/<br />
├── Script/&nbsp;&nbsp;&nbsp;&nbsp; ← con el script dentro<br />
└── docker/&nbsp;&nbsp;&nbsp;&nbsp; ← vacía de momento</code></div></div><br />
<span style="font-weight: bold;" class="mycode_b"><span style="font-size: large;" class="mycode_size">Archivo 1 de 7 - docker/Dockerfile</span></span><ul class="mycode_list"><li><span style="font-weight: bold;" class="mycode_b">Nombre:</span> <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>Dockerfile</code></div></div> (sin extensión)<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">Dónde:</span> dentro de la carpeta <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>docker/</code></div></div></li>
<li><span style="font-weight: bold;" class="mycode_b">Ruta:</span> <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>phpost/docker/Dockerfile</code></div></div></li>
</ul>
Es el archivo que contiene todos los pasos que construye el contenedor de PHP + Apache con todas las extensiones que el script necesita.<br />
 <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>FROM php:8.2-apache<br />
<br />
# --- Extensiones de sistema necesarias para GD y utilidades ---<br />
RUN apt-get update &amp;&amp; apt-get install -y --no-install-recommends &#92;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;libpng-dev &#92;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;libjpeg62-turbo-dev &#92;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;libfreetype6-dev &#92;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;libwebp-dev &#92;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;libonig-dev &#92;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;libzip-dev &#92;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;libssl-dev &#92;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;curl &#92;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;unzip &#92;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&amp;&amp; rm -rf /var/lib/apt/lists/*<br />
<br />
# --- Extensiones PHP obligatorias/recomendadas (REQUISITOS.txt) ---<br />
#&nbsp;&nbsp;mysqli, mbstring, gd, json(core), session(core), fileinfo(core),<br />
#&nbsp;&nbsp;openssl(core), curl, zip<br />
RUN docker-php-ext-configure gd &#92;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;--with-freetype &#92;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;--with-jpeg &#92;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;--with-webp &#92;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&amp;&amp; docker-php-ext-install -j"&#36;(nproc)" &#92;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mysqli &#92;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mbstring &#92;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;gd &#92;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;zip<br />
<br />
# --- Apache: mod_rewrite + mod_headers (URLs limpias y cabeceras) ---<br />
RUN a2enmod rewrite headers<br />
<br />
# --- Config PHP a valores recomendados ---<br />
COPY docker/php.ini /usr/local/etc/php/conf.d/zz-phpost.ini<br />
<br />
# --- VirtualHost con AllowOverride All para que funcione el .htaccess ---<br />
COPY docker/vhost.conf /etc/apache2/sites-available/000-default.conf<br />
<br />
# --- Entrypoint: fija permisos de carpetas escribibles al arrancar ---<br />
COPY docker/entrypoint.sh /usr/local/bin/entrypoint.sh<br />
RUN chmod +x /usr/local/bin/entrypoint.sh<br />
<br />
ENTRYPOINT ["entrypoint.sh"]<br />
CMD ["apache2-foreground"]</code></div></div><br />
<span style="font-weight: bold;" class="mycode_b">Qué hace:</span> parte de PHP 8.2 con Apache, instala las extensiones obligatorias (<br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>mysqli</code></div></div>, <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>gd</code></div></div>, <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>mbstring</code></div></div>, <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>zip</code></div></div>), activa <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>mod_rewrite</code></div></div> para las URLs limpias, y prepara los tres archivos de configuración que creamos a continuación.<br />
<blockquote class="mycode_quote"><cite>Cita:</cite>💡 GD se configura con <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>--with-freetype --with-jpeg --with-webp</code></div></div> <span style="font-weight: bold;" class="mycode_b">antes</span> de instalarse, o no podrá generar miniaturas ni avatares.</blockquote>
<br />
<span style="font-weight: bold;" class="mycode_b"><span style="font-size: large;" class="mycode_size">Archivo 2 de 7 - docker/php.ini</span></span><ul class="mycode_list"><li><span style="font-weight: bold;" class="mycode_b">Nombre:</span> <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>php.ini</code></div></div></li>
<li><span style="font-weight: bold;" class="mycode_b">Dónde:</span> dentro de <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>docker/</code></div></div></li>
<li><span style="font-weight: bold;" class="mycode_b">Ruta:</span> <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>phpost/docker/php.ini</code></div></div></li>
</ul>
Los ajustes de PHP que recomienda el <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>REQUISITOS.txt</code></div></div> del script.<br />
 <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>; Valores recomendados por PHPost / Risus Nova (REQUISITOS.txt)<br />
upload_max_filesize = 8M<br />
post_max_size = 8M<br />
max_execution_time = 60<br />
memory_limit = 128M<br />
<br />
; allow_url_fopen: comprobador de versiones, login Google, *****, StopForumSpam<br />
allow_url_fopen = On<br />
<br />
; Zona horaria (ajusta a tu region)<br />
date.timezone = "Europe/Madrid"<br />
<br />
expose_php = Off</code></div></div><blockquote class="mycode_quote"><cite>Cita:</cite>El <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>allow_url_fopen = On</code></div></div> es importante: sin él pierdes el comprobador de versiones, el login con Google, las notificaciones de ***** y Stop Forum Spam.</blockquote>
<br />
<span style="font-weight: bold;" class="mycode_b"><span style="font-size: large;" class="mycode_size">Archivo 3 de 7 - docker/vhost.conf</span></span><ul class="mycode_list"><li><span style="font-weight: bold;" class="mycode_b">Nombre:</span> <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>vhost.conf</code></div></div></li>
<li><span style="font-weight: bold;" class="mycode_b">Dónde:</span> dentro de <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>docker/</code></div></div></li>
<li><span style="font-weight: bold;" class="mycode_b">Ruta:</span> <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>phpost/docker/vhost.conf</code></div></div></li>
</ul>
Configuración de Apache. <span style="font-weight: bold;" class="mycode_b">La línea clave es <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>AllowOverride All</code></div></div></span>, sin ella el <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>.htaccess</code></div></div> del script se ignora y las URLs dan 404.<br />
 <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>&lt;VirtualHost *:80&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;ServerAdmin webmaster@localhost<br />
&nbsp;&nbsp;&nbsp;&nbsp;DocumentRoot /var/www/html<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;Directory /var/www/html&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Options +FollowSymLinks<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;AllowOverride All<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Require all granted<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;/Directory&gt;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;ErrorLog &#36;{APACHE_LOG_DIR}/error.log<br />
&nbsp;&nbsp;&nbsp;&nbsp;CustomLog &#36;{APACHE_LOG_DIR}/access.log combined<br />
&lt;/VirtualHost&gt;</code></div></div><br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Archivo 4 de 7 - docker/entrypoint.sh</span></span><ul class="mycode_list"><li><span style="font-weight: bold;" class="mycode_b">Nombre:</span> <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>entrypoint.sh</code></div></div></li>
<li><span style="font-weight: bold;" class="mycode_b">Dónde:</span> dentro de <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>docker/</code></div></div></li>
<li><span style="font-weight: bold;" class="mycode_b">Ruta:</span> <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>mi-phpost/docker/entrypoint.sh</code></div></div></li>
</ul>
Este script se ejecuta cada vez que arranca el contenedor y <span style="font-weight: bold;" class="mycode_b">arregla los permisos de las carpetas escribibles automáticamente</span> (las mismas que el instalador te pide poner en 777).<br />
 <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>#!/bin/bash<br />
set -e<br />
<br />
# Carpetas que deben tener permisos de escritura (REQUISITOS.txt)<br />
WRITABLE_DIRS=(<br />
&nbsp;&nbsp;&nbsp;&nbsp;"cache"<br />
&nbsp;&nbsp;&nbsp;&nbsp;"templates_c"<br />
&nbsp;&nbsp;&nbsp;&nbsp;"files/uploads"<br />
&nbsp;&nbsp;&nbsp;&nbsp;"files/images"<br />
&nbsp;&nbsp;&nbsp;&nbsp;"files/avatar"<br />
&nbsp;&nbsp;&nbsp;&nbsp;"files/posts"<br />
&nbsp;&nbsp;&nbsp;&nbsp;"themes"<br />
&nbsp;&nbsp;&nbsp;&nbsp;"inc/smarty/templates_c"<br />
)<br />
<br />
cd /var/www/html<br />
<br />
for dir in "&#36;{WRITABLE_DIRS[@]}"; do<br />
&nbsp;&nbsp;&nbsp;&nbsp;mkdir -p "&#36;dir" 2&gt;/dev/null || true<br />
&nbsp;&nbsp;&nbsp;&nbsp;chown -R www-data:www-data "&#36;dir" 2&gt;/dev/null || true<br />
&nbsp;&nbsp;&nbsp;&nbsp;chmod -R 777 "&#36;dir" 2&gt;/dev/null || true<br />
done<br />
<br />
exec "&#36;@"</code></div></div><blockquote class="mycode_quote"><cite>Cita:</cite>⚠️ <span style="font-weight: bold;" class="mycode_b">MUY IMPORTANTE en Windows:</span> guarda este archivo con saltos de línea <span style="font-weight: bold;" class="mycode_b">LF</span> (Unix), NO CRLF (Windows). Si lo guardas en formato Windows, el contenedor no arrancará y dará un error raro tipo <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>exec format error</code></div></div>. En VS Code lo cambias en la esquina inferior derecha: haz clic donde pone <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>CRLF</code></div></div> y elige <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>LF</code></div></div>.</blockquote>
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Archivo 5 de 7 — docker-compose.yml</span></span><ul class="mycode_list"><li><span style="font-weight: bold;" class="mycode_b">Nombre:</span> <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>docker-compose.yml</code></div></div></li>
<li><span style="font-weight: bold;" class="mycode_b">Dónde:</span> en la <span style="font-weight: bold;" class="mycode_b">raíz</span> del proyecto (al lado de <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>Script/</code></div></div> y <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>docker/</code></div></div>)<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">Ruta:</span> <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>mi-phpost/docker-compose.yml</code></div></div></li>
</ul>
El director de orquesta. Junta la app, la base de datos y los extras opcionales.<br />
 <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>services:<br />
&nbsp;&nbsp;# ---------------------------------------------------------------<br />
&nbsp;&nbsp;#&nbsp;&nbsp;Aplicacion: PHP 8.2 + Apache (Risus Nova / PHPost)<br />
&nbsp;&nbsp;# ---------------------------------------------------------------<br />
&nbsp;&nbsp;app:<br />
&nbsp;&nbsp;&nbsp;&nbsp;build:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;context: .<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dockerfile: docker/Dockerfile<br />
&nbsp;&nbsp;&nbsp;&nbsp;container_name: phpost_app<br />
&nbsp;&nbsp;&nbsp;&nbsp;restart: unless-stopped<br />
&nbsp;&nbsp;&nbsp;&nbsp;depends_on:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;db:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;condition: service_healthy<br />
&nbsp;&nbsp;&nbsp;&nbsp;ports:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;- "&#36;{APP_PORT:-8080}:80"<br />
&nbsp;&nbsp;&nbsp;&nbsp;volumes:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# Codigo del script (uploads persisten en el host)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;- ./Script:/var/www/html<br />
&nbsp;&nbsp;&nbsp;&nbsp;environment:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;TZ: &#36;{TZ:-Europe/Madrid}<br />
&nbsp;&nbsp;&nbsp;&nbsp;networks:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;- phpost<br />
<br />
&nbsp;&nbsp;# ---------------------------------------------------------------<br />
&nbsp;&nbsp;#&nbsp;&nbsp;Base de datos: MariaDB 10.11<br />
&nbsp;&nbsp;# ---------------------------------------------------------------<br />
&nbsp;&nbsp;db:<br />
&nbsp;&nbsp;&nbsp;&nbsp;image: mariadb:10.11<br />
&nbsp;&nbsp;&nbsp;&nbsp;container_name: phpost_db<br />
&nbsp;&nbsp;&nbsp;&nbsp;restart: unless-stopped<br />
&nbsp;&nbsp;&nbsp;&nbsp;environment:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;MARIADB_ROOT_PASSWORD: &#36;{DB_ROOT_PASSWORD}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;MARIADB_DATABASE: &#36;{DB_NAME}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;MARIADB_USER: &#36;{DB_USER}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;MARIADB_PASSWORD: &#36;{DB_PASSWORD}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;TZ: &#36;{TZ:-Europe/Madrid}<br />
&nbsp;&nbsp;&nbsp;&nbsp;volumes:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;- db_data:/var/lib/mysql<br />
&nbsp;&nbsp;&nbsp;&nbsp;healthcheck:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;test: ["CMD", "healthcheck.sh", "--connect", "--innodb_initialized"]<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;interval: 10s<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;timeout: 5s<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;retries: 10<br />
&nbsp;&nbsp;&nbsp;&nbsp;networks:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;- phpost<br />
<br />
&nbsp;&nbsp;# ---------------------------------------------------------------<br />
&nbsp;&nbsp;#&nbsp;&nbsp;Cron: llama a cron.php de forma periodica (opcional)<br />
&nbsp;&nbsp;#&nbsp;&nbsp;Activar con:&nbsp;&nbsp;docker compose --profile cron up -d<br />
&nbsp;&nbsp;# ---------------------------------------------------------------<br />
&nbsp;&nbsp;cron:<br />
&nbsp;&nbsp;&nbsp;&nbsp;image: curlimages/curl:latest<br />
&nbsp;&nbsp;&nbsp;&nbsp;container_name: phpost_cron<br />
&nbsp;&nbsp;&nbsp;&nbsp;restart: unless-stopped<br />
&nbsp;&nbsp;&nbsp;&nbsp;depends_on:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;- app<br />
&nbsp;&nbsp;&nbsp;&nbsp;profiles: ["cron"]<br />
&nbsp;&nbsp;&nbsp;&nbsp;entrypoint: &gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sh -c "while true; do<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;curl -s -o /dev/null Registrate o inicia tu sesión para ver este contenido || true;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sleep &#36;{CRON_INTERVAL:-300};<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;done"<br />
&nbsp;&nbsp;&nbsp;&nbsp;networks:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;- phpost<br />
<br />
&nbsp;&nbsp;# ---------------------------------------------------------------<br />
&nbsp;&nbsp;#&nbsp;&nbsp;phpMyAdmin (opcional, gestion de BD)<br />
&nbsp;&nbsp;#&nbsp;&nbsp;Activar con:&nbsp;&nbsp;docker compose --profile tools up -d<br />
&nbsp;&nbsp;# ---------------------------------------------------------------<br />
&nbsp;&nbsp;phpmyadmin:<br />
&nbsp;&nbsp;&nbsp;&nbsp;image: phpmyadmin:latest<br />
&nbsp;&nbsp;&nbsp;&nbsp;container_name: phpost_pma<br />
&nbsp;&nbsp;&nbsp;&nbsp;restart: unless-stopped<br />
&nbsp;&nbsp;&nbsp;&nbsp;depends_on:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;- db<br />
&nbsp;&nbsp;&nbsp;&nbsp;profiles: ["tools"]<br />
&nbsp;&nbsp;&nbsp;&nbsp;ports:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;- "&#36;{PMA_PORT:-8081}:80"<br />
&nbsp;&nbsp;&nbsp;&nbsp;environment:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PMA_HOST: db<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;UPLOAD_LIMIT: 64M<br />
&nbsp;&nbsp;&nbsp;&nbsp;networks:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;- phpost<br />
<br />
volumes:<br />
&nbsp;&nbsp;db_data:<br />
&nbsp;&nbsp;&nbsp;&nbsp;driver: local<br />
<br />
networks:<br />
&nbsp;&nbsp;phpost:<br />
&nbsp;&nbsp;&nbsp;&nbsp;driver: bridge</code></div></div><br />
<span style="font-weight: bold;" class="mycode_b">Detalles que importan:</span><ul class="mycode_list"><li><div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>depends_on ... condition: service_healthy</code></div></div> -&gt; la app espera a que MySQL esté <span style="font-weight: bold;" class="mycode_b">realmente</span> listo.<br />
</li>
<li>Los servicios <div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>cron</code></div></div> y <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>phpmyadmin</code></div></div> tienen <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>profiles</code></div></div>, así que <span style="font-weight: bold;" class="mycode_b">NO arrancan</span> salvo que tú los pidas (más abajo te explico cómo).<br />
</li>
</ul>
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Archivo 6 de 7 - <span style="color: #999999;" class="mycode_color">.env.example</span></span></span><ul class="mycode_list"><li><span style="font-weight: bold;" class="mycode_b">Nombre:</span> <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>.env.example</code></div></div></li>
<li><span style="font-weight: bold;" class="mycode_b">Dónde:</span> en la <span style="font-weight: bold;" class="mycode_b">raíz</span> del proyecto<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">Ruta:</span> <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>mi-phpost/.env.example</code></div></div></li>
</ul>
La <span style="font-weight: bold;" class="mycode_b">plantilla</span> de configuración. Aquí van puertos y contraseñas. La subes al repositorio sin miedo porque no tiene contraseñas reales.<br />
 <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code># -------- Puertos host --------<br />
APP_PORT=8080&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# Registrate o inicia tu sesión para ver este contenido<br />
PMA_PORT=8081&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# phpMyAdmin (perfil tools)<br />
<br />
# -------- Base de datos --------<br />
# Estos valores son los que introduces en el instalador web.<br />
# Hostname de BD en el instalador&nbsp;&nbsp;=&nbsp;&nbsp;db&nbsp;&nbsp; (nombre del servicio)<br />
DB_NAME=phpost<br />
DB_USER=phpost<br />
DB_PASSWORD=cambia_esta_password<br />
DB_ROOT_PASSWORD=cambia_esta_root_password<br />
<br />
# -------- Cron (perfil cron) --------<br />
CRON_INTERVAL=300&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# segundos entre llamadas a cron.php<br />
<br />
# -------- Zona horaria --------<br />
TZ=America/Bogota</code></div></div><br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Archivo 7 de 7 - .dockerignore</span></span><ul class="mycode_list"><li><span style="font-weight: bold;" class="mycode_b">Nombre:</span> <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>.dockerignore</code></div></div></li>
<li><span style="font-weight: bold;" class="mycode_b">Dónde:</span> en la <span style="font-weight: bold;" class="mycode_b">raíz</span> del proyecto<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">Ruta:</span> <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>mi-phpost/.dockerignore</code></div></div></li>
</ul>
Le dice a Docker qué NO meter dentro de la imagen (archivos que no hacen falta).<br />
 <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>.git<br />
*.md<br />
CHANGELOG.txt<br />
LEEME.txt<br />
REQUISITOS.txt<br />
*.url<br />
.env</code></div></div><br />
<span style="color: #16a085;" class="mycode_color"><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Comprobación: ¿tienes todo?</span></span></span><br />
Antes de arrancar, revisa que tu carpeta tiene estos archivos y esta estrucutra:<br />
 <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>phpost/<br />
├── Script/&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;← el script (ya lo tenías)<br />
├── docker/<br />
│&nbsp;&nbsp; ├── Dockerfile&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ✔ archivo 1<br />
│&nbsp;&nbsp; ├── php.ini&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;✔ archivo 2<br />
│&nbsp;&nbsp; ├── vhost.conf&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ✔ archivo 3<br />
│&nbsp;&nbsp; └── entrypoint.sh&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;✔ archivo 4&nbsp;&nbsp;(¡en formato LF!)<br />
├── docker-compose.yml&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ✔ archivo 5<br />
├── .env.example&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ✔ archivo 6<br />
└── .dockerignore&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;✔ archivo 7</code></div></div><br />
<br />
<span style="color: #3498db;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b"><span style="font-size: large;" class="mycode_size">Ahora solamente falta arrancar el proyecto</span></span></span><br />
Abre una terminal <span style="font-weight: bold;" class="mycode_b">dentro de la carpeta <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>phpost/</code></div></div></span> y ejecuta:<br />
 <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code># 1. Crea tu .env real a partir de la plantilla<br />
cp .env.example .env</code></div></div><br />
Ahora <span style="font-weight: bold;" class="mycode_b">edita el <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>.env</code></div></div></span> y cambia <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>DB_PASSWORD</code></div></div> y <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>DB_ROOT_PASSWORD</code></div></div> por contraseñas de verdad.<br />
<blockquote class="mycode_quote"><cite>Cita:</cite>🔑 Para generar una contraseña segura: <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>openssl rand -base64 18</code></div></div> (en Linux, Mac o Git Bash de Windows).</blockquote>
 <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code># 2. Construye y arranca todo<br />
docker compose up -d --build</code></div></div> Espera un par de minutos la primera vez (se descarga y construye la imagen). Cuando termine:<ul class="mycode_list"><li>La web está en <span style="font-weight: bold;" class="mycode_b"><a href="http://Registrate%20o%20inicia%20tu%20sesión%20para%20ver%20este%20contenido" target="_blank" rel="noopener" class="mycode_url">Registrate o inicia tu sesión para ver este contenido</a></span><br />
</li>
<li>La base de datos corriendo por dentro<br />
</li>
</ul>
Para comprobar que todo está arriba:<br />
<blockquote class="mycode_quote"><cite>Cita:</cite>docker compose ps</blockquote>
<br />
Debes ver <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>phpost_app</code></div></div> y <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>phpost_db</code></div></div> con estado <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>Up</code></div></div> (y la BD como <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>healthy</code></div></div>).<br />
<br />
El instalador web<br />
<br />
Abre <span style="font-weight: bold;" class="mycode_b"><a href="http://Registrate%20o%20inicia%20tu%20sesión%20para%20ver%20este%20contenido" target="_blank" rel="noopener" class="mycode_url">http://Registrate o inicia tu sesión par... contenido</a></span> y sigue el asistente.<br />
<br />
<span style="color: #f39c12;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b"><span style="font-size: medium;" class="mycode_size">Permisos de archivos</span></span></span><br />
<br />
El instalador comprobará los permisos de las carpetas. Gracias al <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>entrypoint.sh</code></div></div>, <span style="font-weight: bold;" class="mycode_b">deberían salir todos en OK (777) automáticamente.</span> Si alguno sale en NO, reinicia el contenedor con <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>docker compose restart app</code></div></div> y recarga.<br />
<br />
Datos de la base de datos<br />
Aquí es donde falla casi todo el mundo. Pon <span style="font-weight: bold;" class="mycode_b">exactamente</span> esto:<br />
<br />
<img src="https://i.postimg.cc/k5qJyKFZ/Screenshot-2026-07-11-201633.png" loading="lazy"  alt="[Imagen: Screenshot-2026-07-11-201633.png]" class="mycode_img img-responsive" /><br />
<br />
<span style="font-size: medium;" class="mycode_size"><span style="color: #f39c12;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">El error nº1: poner "localhost"</span></span></span><br />
 En Docker cada contenedor es como un ordenador independiente. Si pones <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>localhost</code></div></div>, la app busca la base de datos <span style="font-weight: bold;" class="mycode_b">dentro de sí misma</span> y no la encuentra. Hay que usar el <span style="font-weight: bold;" class="mycode_b">nombre del servicio</span>: <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>db</code></div></div>. Docker se encarga de que ese nombre apunte al contenedor de MySQL en su red interna.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">Grábate esto: el servidor de la base de datos es <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>db</code></div></div>, no <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>localhost</code></div></div>.</span><br />
<br />
<span style="color: #f39c12;" class="mycode_color"><span style="font-size: medium;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">¿Dónde se guardan mis datos? (volúmenes)</span></span></span><br />
 Un contenedor es efímero: si lo borras, se lleva todo lo de dentro. Por eso los datos importantes viven <span style="font-weight: bold;" class="mycode_b">fuera</span>, en volúmenes. En este montaje hay dos:<br />
<ol type="1" class="mycode_list"><li><span style="font-weight: bold;" class="mycode_b">Base de datos → volumen <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>db_data</code></div></div>.</span> Todos los usuarios, posts y comentarios viven en un volumen que gestiona Docker. Aunque borres y recrees el contenedor, la BD sigue ahí. Solo se pierde con <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>docker compose down -v</code></div></div>.<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">Código y subidas → carpeta <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>Script/</code></div></div> de tu PC</span> (bind-mount <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>./Script:/var/www/html</code></div></div>). Esto tiene dos ventajas:<ul class="mycode_list"><li>Editas un archivo en tu ordenador y el cambio se ve al instante en la web.<br />
</li>
<li>Los avatares, imágenes y posts que suben los usuarios se guardan en <span style="font-weight: bold;" class="mycode_b">tu</span> carpeta <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>Script/files/</code></div></div>, no dentro del contenedor. Así que sobreviven a cualquier cosa.<br />
</li>
</ul>
</li>
</ol>
<br />
Comandos del día a día<br />
 <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>docker compose ps&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; # ver qué está corriendo<br />
docker compose logs -f app&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# ver logs de PHP/Apache<br />
docker compose exec app bash&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# entrar al contenedor<br />
docker compose restart app&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# reiniciar solo la app<br />
docker compose down&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; # parar todo (conserva los datos)<br />
docker compose down -v&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# parar y BORRAR la base de datos ⚠️<br />
docker compose up -d --build&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# reconstruir tras cambiar el Dockerfile</code></div></div><br />
<br />
Espero que les sirva bastante. Dudas y mejoras en los comentarios, saludos!]]></description>
			<content:encoded><![CDATA[Hola!, he vuelto a la comunidad haha, hace un tiempo llevo desarollando otro script y me dió por instalar PHPost para ver como ha evolucionado y si puedo ayudar a mejorar en mis tiempos libres, como hoy que me ha entrado las ganas de instalar el script en mi server con docker y si alguno necesita un paso a paso de como hacerlo, esta es la guía definitiva, me gustaría que si hay mejoras o correcciones de typo por ejemplo, o mejoras en cuanto a docker me escriban, por ahora, nada más que decir, solamente agradecer a los desarrolladores que siguieron aquí haciendo posible esta comunidad.<br />
<br />
Guía completa: PHPost (Risus Nova) con Docker desde cero<br />
<br />
Te digo <span style="font-weight: bold;" class="mycode_b">exactamente qué archivos crear, con qué nombre, dónde guardarlos y qué escribir dentro de cada uno</span>. Copia, pega y listo.<br />
Funciona igual en Windows, Linux y Mac. No necesitas instalar PHP, ni MySQL, ni Apache: Docker lo trae todo dentro.<br />
<br />
<span style="font-weight: bold;" class="mycode_b"><span style="font-size: large;" class="mycode_size">La estructura final (esto es lo que vamos a construir)</span></span><br />
Cuando termines, tendrás esto:<br />
 <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>phpost/<br />
│<br />
├── Script/&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;← el script Risus Nova<br />
│&nbsp;&nbsp; ├── index.php<br />
│&nbsp;&nbsp; ├── config.inc.php<br />
│&nbsp;&nbsp; ├── install/<br />
│&nbsp;&nbsp; ├── files/<br />
│&nbsp;&nbsp; └── ... (todo el contenido del script)<br />
│<br />
├── docker/&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;← carpeta que TÚ creas<br />
│&nbsp;&nbsp; ├── Dockerfile<br />
│&nbsp;&nbsp; ├── php.ini<br />
│&nbsp;&nbsp; ├── vhost.conf<br />
│&nbsp;&nbsp; └── entrypoint.sh<br />
│<br />
├── docker-compose.yml&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ← archivo que TÚ creas<br />
├── .env.example&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ← archivo que TÚ creas (plantilla)<br />
├── .env&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ← copia de .env.example con tus contraseñas<br />
└── .dockerignore&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;← archivo que TÚ creas</code></div></div><br />
En total tienes que crear <span style="font-weight: bold;" class="mycode_b">7 archivos</span> (más la carpeta <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>docker/</code></div></div>). Vamos uno por uno.<br />
<br />
<span style="font-weight: bold;" class="mycode_b"><span style="font-size: large;" class="mycode_size">Paso 0: prepara la carpeta base</span></span><br />
<ol type="1" class="mycode_list"><li>Crea una carpeta para el proyecto. La llamaré <div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>phpost/</code></div></div> pero puedes ponerle el nombre que quieras.<br />
</li>
<li>Descarga Risus Nova de <a href="http://Registrate%20o%20inicia%20tu%20sesión%20para%20ver%20este%20contenido" target="_blank" rel="noopener" class="mycode_url">phpost.es</a> e <span style="font-weight: bold;" class="mycode_b">inserta todo el contenido del script dentro de una subcarpeta llamada <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>Script/</code></div></div></span>.<br />
</li>
<li>Crea una carpeta vacía llamada <div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>docker/</code></div></div> al lado de <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>Script/</code></div></div>.<br />
</li>
</ol>
Quedaría así:<br />
 <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>phpost/<br />
├── Script/&nbsp;&nbsp;&nbsp;&nbsp; ← con el script dentro<br />
└── docker/&nbsp;&nbsp;&nbsp;&nbsp; ← vacía de momento</code></div></div><br />
<span style="font-weight: bold;" class="mycode_b"><span style="font-size: large;" class="mycode_size">Archivo 1 de 7 - docker/Dockerfile</span></span><ul class="mycode_list"><li><span style="font-weight: bold;" class="mycode_b">Nombre:</span> <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>Dockerfile</code></div></div> (sin extensión)<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">Dónde:</span> dentro de la carpeta <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>docker/</code></div></div></li>
<li><span style="font-weight: bold;" class="mycode_b">Ruta:</span> <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>phpost/docker/Dockerfile</code></div></div></li>
</ul>
Es el archivo que contiene todos los pasos que construye el contenedor de PHP + Apache con todas las extensiones que el script necesita.<br />
 <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>FROM php:8.2-apache<br />
<br />
# --- Extensiones de sistema necesarias para GD y utilidades ---<br />
RUN apt-get update &amp;&amp; apt-get install -y --no-install-recommends &#92;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;libpng-dev &#92;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;libjpeg62-turbo-dev &#92;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;libfreetype6-dev &#92;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;libwebp-dev &#92;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;libonig-dev &#92;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;libzip-dev &#92;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;libssl-dev &#92;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;curl &#92;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;unzip &#92;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&amp;&amp; rm -rf /var/lib/apt/lists/*<br />
<br />
# --- Extensiones PHP obligatorias/recomendadas (REQUISITOS.txt) ---<br />
#&nbsp;&nbsp;mysqli, mbstring, gd, json(core), session(core), fileinfo(core),<br />
#&nbsp;&nbsp;openssl(core), curl, zip<br />
RUN docker-php-ext-configure gd &#92;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;--with-freetype &#92;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;--with-jpeg &#92;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;--with-webp &#92;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&amp;&amp; docker-php-ext-install -j"&#36;(nproc)" &#92;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mysqli &#92;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mbstring &#92;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;gd &#92;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;zip<br />
<br />
# --- Apache: mod_rewrite + mod_headers (URLs limpias y cabeceras) ---<br />
RUN a2enmod rewrite headers<br />
<br />
# --- Config PHP a valores recomendados ---<br />
COPY docker/php.ini /usr/local/etc/php/conf.d/zz-phpost.ini<br />
<br />
# --- VirtualHost con AllowOverride All para que funcione el .htaccess ---<br />
COPY docker/vhost.conf /etc/apache2/sites-available/000-default.conf<br />
<br />
# --- Entrypoint: fija permisos de carpetas escribibles al arrancar ---<br />
COPY docker/entrypoint.sh /usr/local/bin/entrypoint.sh<br />
RUN chmod +x /usr/local/bin/entrypoint.sh<br />
<br />
ENTRYPOINT ["entrypoint.sh"]<br />
CMD ["apache2-foreground"]</code></div></div><br />
<span style="font-weight: bold;" class="mycode_b">Qué hace:</span> parte de PHP 8.2 con Apache, instala las extensiones obligatorias (<br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>mysqli</code></div></div>, <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>gd</code></div></div>, <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>mbstring</code></div></div>, <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>zip</code></div></div>), activa <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>mod_rewrite</code></div></div> para las URLs limpias, y prepara los tres archivos de configuración que creamos a continuación.<br />
<blockquote class="mycode_quote"><cite>Cita:</cite>💡 GD se configura con <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>--with-freetype --with-jpeg --with-webp</code></div></div> <span style="font-weight: bold;" class="mycode_b">antes</span> de instalarse, o no podrá generar miniaturas ni avatares.</blockquote>
<br />
<span style="font-weight: bold;" class="mycode_b"><span style="font-size: large;" class="mycode_size">Archivo 2 de 7 - docker/php.ini</span></span><ul class="mycode_list"><li><span style="font-weight: bold;" class="mycode_b">Nombre:</span> <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>php.ini</code></div></div></li>
<li><span style="font-weight: bold;" class="mycode_b">Dónde:</span> dentro de <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>docker/</code></div></div></li>
<li><span style="font-weight: bold;" class="mycode_b">Ruta:</span> <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>phpost/docker/php.ini</code></div></div></li>
</ul>
Los ajustes de PHP que recomienda el <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>REQUISITOS.txt</code></div></div> del script.<br />
 <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>; Valores recomendados por PHPost / Risus Nova (REQUISITOS.txt)<br />
upload_max_filesize = 8M<br />
post_max_size = 8M<br />
max_execution_time = 60<br />
memory_limit = 128M<br />
<br />
; allow_url_fopen: comprobador de versiones, login Google, *****, StopForumSpam<br />
allow_url_fopen = On<br />
<br />
; Zona horaria (ajusta a tu region)<br />
date.timezone = "Europe/Madrid"<br />
<br />
expose_php = Off</code></div></div><blockquote class="mycode_quote"><cite>Cita:</cite>El <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>allow_url_fopen = On</code></div></div> es importante: sin él pierdes el comprobador de versiones, el login con Google, las notificaciones de ***** y Stop Forum Spam.</blockquote>
<br />
<span style="font-weight: bold;" class="mycode_b"><span style="font-size: large;" class="mycode_size">Archivo 3 de 7 - docker/vhost.conf</span></span><ul class="mycode_list"><li><span style="font-weight: bold;" class="mycode_b">Nombre:</span> <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>vhost.conf</code></div></div></li>
<li><span style="font-weight: bold;" class="mycode_b">Dónde:</span> dentro de <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>docker/</code></div></div></li>
<li><span style="font-weight: bold;" class="mycode_b">Ruta:</span> <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>phpost/docker/vhost.conf</code></div></div></li>
</ul>
Configuración de Apache. <span style="font-weight: bold;" class="mycode_b">La línea clave es <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>AllowOverride All</code></div></div></span>, sin ella el <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>.htaccess</code></div></div> del script se ignora y las URLs dan 404.<br />
 <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>&lt;VirtualHost *:80&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;ServerAdmin webmaster@localhost<br />
&nbsp;&nbsp;&nbsp;&nbsp;DocumentRoot /var/www/html<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;Directory /var/www/html&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Options +FollowSymLinks<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;AllowOverride All<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Require all granted<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;/Directory&gt;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;ErrorLog &#36;{APACHE_LOG_DIR}/error.log<br />
&nbsp;&nbsp;&nbsp;&nbsp;CustomLog &#36;{APACHE_LOG_DIR}/access.log combined<br />
&lt;/VirtualHost&gt;</code></div></div><br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Archivo 4 de 7 - docker/entrypoint.sh</span></span><ul class="mycode_list"><li><span style="font-weight: bold;" class="mycode_b">Nombre:</span> <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>entrypoint.sh</code></div></div></li>
<li><span style="font-weight: bold;" class="mycode_b">Dónde:</span> dentro de <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>docker/</code></div></div></li>
<li><span style="font-weight: bold;" class="mycode_b">Ruta:</span> <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>mi-phpost/docker/entrypoint.sh</code></div></div></li>
</ul>
Este script se ejecuta cada vez que arranca el contenedor y <span style="font-weight: bold;" class="mycode_b">arregla los permisos de las carpetas escribibles automáticamente</span> (las mismas que el instalador te pide poner en 777).<br />
 <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>#!/bin/bash<br />
set -e<br />
<br />
# Carpetas que deben tener permisos de escritura (REQUISITOS.txt)<br />
WRITABLE_DIRS=(<br />
&nbsp;&nbsp;&nbsp;&nbsp;"cache"<br />
&nbsp;&nbsp;&nbsp;&nbsp;"templates_c"<br />
&nbsp;&nbsp;&nbsp;&nbsp;"files/uploads"<br />
&nbsp;&nbsp;&nbsp;&nbsp;"files/images"<br />
&nbsp;&nbsp;&nbsp;&nbsp;"files/avatar"<br />
&nbsp;&nbsp;&nbsp;&nbsp;"files/posts"<br />
&nbsp;&nbsp;&nbsp;&nbsp;"themes"<br />
&nbsp;&nbsp;&nbsp;&nbsp;"inc/smarty/templates_c"<br />
)<br />
<br />
cd /var/www/html<br />
<br />
for dir in "&#36;{WRITABLE_DIRS[@]}"; do<br />
&nbsp;&nbsp;&nbsp;&nbsp;mkdir -p "&#36;dir" 2&gt;/dev/null || true<br />
&nbsp;&nbsp;&nbsp;&nbsp;chown -R www-data:www-data "&#36;dir" 2&gt;/dev/null || true<br />
&nbsp;&nbsp;&nbsp;&nbsp;chmod -R 777 "&#36;dir" 2&gt;/dev/null || true<br />
done<br />
<br />
exec "&#36;@"</code></div></div><blockquote class="mycode_quote"><cite>Cita:</cite>⚠️ <span style="font-weight: bold;" class="mycode_b">MUY IMPORTANTE en Windows:</span> guarda este archivo con saltos de línea <span style="font-weight: bold;" class="mycode_b">LF</span> (Unix), NO CRLF (Windows). Si lo guardas en formato Windows, el contenedor no arrancará y dará un error raro tipo <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>exec format error</code></div></div>. En VS Code lo cambias en la esquina inferior derecha: haz clic donde pone <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>CRLF</code></div></div> y elige <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>LF</code></div></div>.</blockquote>
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Archivo 5 de 7 — docker-compose.yml</span></span><ul class="mycode_list"><li><span style="font-weight: bold;" class="mycode_b">Nombre:</span> <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>docker-compose.yml</code></div></div></li>
<li><span style="font-weight: bold;" class="mycode_b">Dónde:</span> en la <span style="font-weight: bold;" class="mycode_b">raíz</span> del proyecto (al lado de <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>Script/</code></div></div> y <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>docker/</code></div></div>)<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">Ruta:</span> <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>mi-phpost/docker-compose.yml</code></div></div></li>
</ul>
El director de orquesta. Junta la app, la base de datos y los extras opcionales.<br />
 <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>services:<br />
&nbsp;&nbsp;# ---------------------------------------------------------------<br />
&nbsp;&nbsp;#&nbsp;&nbsp;Aplicacion: PHP 8.2 + Apache (Risus Nova / PHPost)<br />
&nbsp;&nbsp;# ---------------------------------------------------------------<br />
&nbsp;&nbsp;app:<br />
&nbsp;&nbsp;&nbsp;&nbsp;build:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;context: .<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dockerfile: docker/Dockerfile<br />
&nbsp;&nbsp;&nbsp;&nbsp;container_name: phpost_app<br />
&nbsp;&nbsp;&nbsp;&nbsp;restart: unless-stopped<br />
&nbsp;&nbsp;&nbsp;&nbsp;depends_on:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;db:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;condition: service_healthy<br />
&nbsp;&nbsp;&nbsp;&nbsp;ports:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;- "&#36;{APP_PORT:-8080}:80"<br />
&nbsp;&nbsp;&nbsp;&nbsp;volumes:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# Codigo del script (uploads persisten en el host)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;- ./Script:/var/www/html<br />
&nbsp;&nbsp;&nbsp;&nbsp;environment:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;TZ: &#36;{TZ:-Europe/Madrid}<br />
&nbsp;&nbsp;&nbsp;&nbsp;networks:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;- phpost<br />
<br />
&nbsp;&nbsp;# ---------------------------------------------------------------<br />
&nbsp;&nbsp;#&nbsp;&nbsp;Base de datos: MariaDB 10.11<br />
&nbsp;&nbsp;# ---------------------------------------------------------------<br />
&nbsp;&nbsp;db:<br />
&nbsp;&nbsp;&nbsp;&nbsp;image: mariadb:10.11<br />
&nbsp;&nbsp;&nbsp;&nbsp;container_name: phpost_db<br />
&nbsp;&nbsp;&nbsp;&nbsp;restart: unless-stopped<br />
&nbsp;&nbsp;&nbsp;&nbsp;environment:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;MARIADB_ROOT_PASSWORD: &#36;{DB_ROOT_PASSWORD}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;MARIADB_DATABASE: &#36;{DB_NAME}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;MARIADB_USER: &#36;{DB_USER}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;MARIADB_PASSWORD: &#36;{DB_PASSWORD}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;TZ: &#36;{TZ:-Europe/Madrid}<br />
&nbsp;&nbsp;&nbsp;&nbsp;volumes:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;- db_data:/var/lib/mysql<br />
&nbsp;&nbsp;&nbsp;&nbsp;healthcheck:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;test: ["CMD", "healthcheck.sh", "--connect", "--innodb_initialized"]<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;interval: 10s<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;timeout: 5s<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;retries: 10<br />
&nbsp;&nbsp;&nbsp;&nbsp;networks:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;- phpost<br />
<br />
&nbsp;&nbsp;# ---------------------------------------------------------------<br />
&nbsp;&nbsp;#&nbsp;&nbsp;Cron: llama a cron.php de forma periodica (opcional)<br />
&nbsp;&nbsp;#&nbsp;&nbsp;Activar con:&nbsp;&nbsp;docker compose --profile cron up -d<br />
&nbsp;&nbsp;# ---------------------------------------------------------------<br />
&nbsp;&nbsp;cron:<br />
&nbsp;&nbsp;&nbsp;&nbsp;image: curlimages/curl:latest<br />
&nbsp;&nbsp;&nbsp;&nbsp;container_name: phpost_cron<br />
&nbsp;&nbsp;&nbsp;&nbsp;restart: unless-stopped<br />
&nbsp;&nbsp;&nbsp;&nbsp;depends_on:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;- app<br />
&nbsp;&nbsp;&nbsp;&nbsp;profiles: ["cron"]<br />
&nbsp;&nbsp;&nbsp;&nbsp;entrypoint: &gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sh -c "while true; do<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;curl -s -o /dev/null Registrate o inicia tu sesión para ver este contenido || true;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sleep &#36;{CRON_INTERVAL:-300};<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;done"<br />
&nbsp;&nbsp;&nbsp;&nbsp;networks:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;- phpost<br />
<br />
&nbsp;&nbsp;# ---------------------------------------------------------------<br />
&nbsp;&nbsp;#&nbsp;&nbsp;phpMyAdmin (opcional, gestion de BD)<br />
&nbsp;&nbsp;#&nbsp;&nbsp;Activar con:&nbsp;&nbsp;docker compose --profile tools up -d<br />
&nbsp;&nbsp;# ---------------------------------------------------------------<br />
&nbsp;&nbsp;phpmyadmin:<br />
&nbsp;&nbsp;&nbsp;&nbsp;image: phpmyadmin:latest<br />
&nbsp;&nbsp;&nbsp;&nbsp;container_name: phpost_pma<br />
&nbsp;&nbsp;&nbsp;&nbsp;restart: unless-stopped<br />
&nbsp;&nbsp;&nbsp;&nbsp;depends_on:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;- db<br />
&nbsp;&nbsp;&nbsp;&nbsp;profiles: ["tools"]<br />
&nbsp;&nbsp;&nbsp;&nbsp;ports:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;- "&#36;{PMA_PORT:-8081}:80"<br />
&nbsp;&nbsp;&nbsp;&nbsp;environment:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PMA_HOST: db<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;UPLOAD_LIMIT: 64M<br />
&nbsp;&nbsp;&nbsp;&nbsp;networks:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;- phpost<br />
<br />
volumes:<br />
&nbsp;&nbsp;db_data:<br />
&nbsp;&nbsp;&nbsp;&nbsp;driver: local<br />
<br />
networks:<br />
&nbsp;&nbsp;phpost:<br />
&nbsp;&nbsp;&nbsp;&nbsp;driver: bridge</code></div></div><br />
<span style="font-weight: bold;" class="mycode_b">Detalles que importan:</span><ul class="mycode_list"><li><div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>depends_on ... condition: service_healthy</code></div></div> -&gt; la app espera a que MySQL esté <span style="font-weight: bold;" class="mycode_b">realmente</span> listo.<br />
</li>
<li>Los servicios <div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>cron</code></div></div> y <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>phpmyadmin</code></div></div> tienen <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>profiles</code></div></div>, así que <span style="font-weight: bold;" class="mycode_b">NO arrancan</span> salvo que tú los pidas (más abajo te explico cómo).<br />
</li>
</ul>
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Archivo 6 de 7 - <span style="color: #999999;" class="mycode_color">.env.example</span></span></span><ul class="mycode_list"><li><span style="font-weight: bold;" class="mycode_b">Nombre:</span> <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>.env.example</code></div></div></li>
<li><span style="font-weight: bold;" class="mycode_b">Dónde:</span> en la <span style="font-weight: bold;" class="mycode_b">raíz</span> del proyecto<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">Ruta:</span> <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>mi-phpost/.env.example</code></div></div></li>
</ul>
La <span style="font-weight: bold;" class="mycode_b">plantilla</span> de configuración. Aquí van puertos y contraseñas. La subes al repositorio sin miedo porque no tiene contraseñas reales.<br />
 <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code># -------- Puertos host --------<br />
APP_PORT=8080&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# Registrate o inicia tu sesión para ver este contenido<br />
PMA_PORT=8081&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# phpMyAdmin (perfil tools)<br />
<br />
# -------- Base de datos --------<br />
# Estos valores son los que introduces en el instalador web.<br />
# Hostname de BD en el instalador&nbsp;&nbsp;=&nbsp;&nbsp;db&nbsp;&nbsp; (nombre del servicio)<br />
DB_NAME=phpost<br />
DB_USER=phpost<br />
DB_PASSWORD=cambia_esta_password<br />
DB_ROOT_PASSWORD=cambia_esta_root_password<br />
<br />
# -------- Cron (perfil cron) --------<br />
CRON_INTERVAL=300&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# segundos entre llamadas a cron.php<br />
<br />
# -------- Zona horaria --------<br />
TZ=America/Bogota</code></div></div><br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Archivo 7 de 7 - .dockerignore</span></span><ul class="mycode_list"><li><span style="font-weight: bold;" class="mycode_b">Nombre:</span> <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>.dockerignore</code></div></div></li>
<li><span style="font-weight: bold;" class="mycode_b">Dónde:</span> en la <span style="font-weight: bold;" class="mycode_b">raíz</span> del proyecto<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">Ruta:</span> <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>mi-phpost/.dockerignore</code></div></div></li>
</ul>
Le dice a Docker qué NO meter dentro de la imagen (archivos que no hacen falta).<br />
 <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>.git<br />
*.md<br />
CHANGELOG.txt<br />
LEEME.txt<br />
REQUISITOS.txt<br />
*.url<br />
.env</code></div></div><br />
<span style="color: #16a085;" class="mycode_color"><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Comprobación: ¿tienes todo?</span></span></span><br />
Antes de arrancar, revisa que tu carpeta tiene estos archivos y esta estrucutra:<br />
 <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>phpost/<br />
├── Script/&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;← el script (ya lo tenías)<br />
├── docker/<br />
│&nbsp;&nbsp; ├── Dockerfile&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ✔ archivo 1<br />
│&nbsp;&nbsp; ├── php.ini&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;✔ archivo 2<br />
│&nbsp;&nbsp; ├── vhost.conf&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ✔ archivo 3<br />
│&nbsp;&nbsp; └── entrypoint.sh&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;✔ archivo 4&nbsp;&nbsp;(¡en formato LF!)<br />
├── docker-compose.yml&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ✔ archivo 5<br />
├── .env.example&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ✔ archivo 6<br />
└── .dockerignore&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;✔ archivo 7</code></div></div><br />
<br />
<span style="color: #3498db;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b"><span style="font-size: large;" class="mycode_size">Ahora solamente falta arrancar el proyecto</span></span></span><br />
Abre una terminal <span style="font-weight: bold;" class="mycode_b">dentro de la carpeta <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>phpost/</code></div></div></span> y ejecuta:<br />
 <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code># 1. Crea tu .env real a partir de la plantilla<br />
cp .env.example .env</code></div></div><br />
Ahora <span style="font-weight: bold;" class="mycode_b">edita el <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>.env</code></div></div></span> y cambia <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>DB_PASSWORD</code></div></div> y <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>DB_ROOT_PASSWORD</code></div></div> por contraseñas de verdad.<br />
<blockquote class="mycode_quote"><cite>Cita:</cite>🔑 Para generar una contraseña segura: <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>openssl rand -base64 18</code></div></div> (en Linux, Mac o Git Bash de Windows).</blockquote>
 <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code># 2. Construye y arranca todo<br />
docker compose up -d --build</code></div></div> Espera un par de minutos la primera vez (se descarga y construye la imagen). Cuando termine:<ul class="mycode_list"><li>La web está en <span style="font-weight: bold;" class="mycode_b"><a href="http://Registrate%20o%20inicia%20tu%20sesión%20para%20ver%20este%20contenido" target="_blank" rel="noopener" class="mycode_url">Registrate o inicia tu sesión para ver este contenido</a></span><br />
</li>
<li>La base de datos corriendo por dentro<br />
</li>
</ul>
Para comprobar que todo está arriba:<br />
<blockquote class="mycode_quote"><cite>Cita:</cite>docker compose ps</blockquote>
<br />
Debes ver <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>phpost_app</code></div></div> y <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>phpost_db</code></div></div> con estado <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>Up</code></div></div> (y la BD como <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>healthy</code></div></div>).<br />
<br />
El instalador web<br />
<br />
Abre <span style="font-weight: bold;" class="mycode_b"><a href="http://Registrate%20o%20inicia%20tu%20sesión%20para%20ver%20este%20contenido" target="_blank" rel="noopener" class="mycode_url">http://Registrate o inicia tu sesión par... contenido</a></span> y sigue el asistente.<br />
<br />
<span style="color: #f39c12;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b"><span style="font-size: medium;" class="mycode_size">Permisos de archivos</span></span></span><br />
<br />
El instalador comprobará los permisos de las carpetas. Gracias al <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>entrypoint.sh</code></div></div>, <span style="font-weight: bold;" class="mycode_b">deberían salir todos en OK (777) automáticamente.</span> Si alguno sale en NO, reinicia el contenedor con <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>docker compose restart app</code></div></div> y recarga.<br />
<br />
Datos de la base de datos<br />
Aquí es donde falla casi todo el mundo. Pon <span style="font-weight: bold;" class="mycode_b">exactamente</span> esto:<br />
<br />
<img src="https://i.postimg.cc/k5qJyKFZ/Screenshot-2026-07-11-201633.png" loading="lazy"  alt="[Imagen: Screenshot-2026-07-11-201633.png]" class="mycode_img img-responsive" /><br />
<br />
<span style="font-size: medium;" class="mycode_size"><span style="color: #f39c12;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">El error nº1: poner "localhost"</span></span></span><br />
 En Docker cada contenedor es como un ordenador independiente. Si pones <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>localhost</code></div></div>, la app busca la base de datos <span style="font-weight: bold;" class="mycode_b">dentro de sí misma</span> y no la encuentra. Hay que usar el <span style="font-weight: bold;" class="mycode_b">nombre del servicio</span>: <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>db</code></div></div>. Docker se encarga de que ese nombre apunte al contenedor de MySQL en su red interna.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">Grábate esto: el servidor de la base de datos es <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>db</code></div></div>, no <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>localhost</code></div></div>.</span><br />
<br />
<span style="color: #f39c12;" class="mycode_color"><span style="font-size: medium;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">¿Dónde se guardan mis datos? (volúmenes)</span></span></span><br />
 Un contenedor es efímero: si lo borras, se lleva todo lo de dentro. Por eso los datos importantes viven <span style="font-weight: bold;" class="mycode_b">fuera</span>, en volúmenes. En este montaje hay dos:<br />
<ol type="1" class="mycode_list"><li><span style="font-weight: bold;" class="mycode_b">Base de datos → volumen <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>db_data</code></div></div>.</span> Todos los usuarios, posts y comentarios viven en un volumen que gestiona Docker. Aunque borres y recrees el contenedor, la BD sigue ahí. Solo se pierde con <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>docker compose down -v</code></div></div>.<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">Código y subidas → carpeta <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>Script/</code></div></div> de tu PC</span> (bind-mount <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>./Script:/var/www/html</code></div></div>). Esto tiene dos ventajas:<ul class="mycode_list"><li>Editas un archivo en tu ordenador y el cambio se ve al instante en la web.<br />
</li>
<li>Los avatares, imágenes y posts que suben los usuarios se guardan en <span style="font-weight: bold;" class="mycode_b">tu</span> carpeta <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>Script/files/</code></div></div>, no dentro del contenedor. Así que sobreviven a cualquier cosa.<br />
</li>
</ul>
</li>
</ol>
<br />
Comandos del día a día<br />
 <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>docker compose ps&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; # ver qué está corriendo<br />
docker compose logs -f app&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# ver logs de PHP/Apache<br />
docker compose exec app bash&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# entrar al contenedor<br />
docker compose restart app&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# reiniciar solo la app<br />
docker compose down&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; # parar todo (conserva los datos)<br />
docker compose down -v&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# parar y BORRAR la base de datos ⚠️<br />
docker compose up -d --build&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# reconstruir tras cambiar el Dockerfile</code></div></div><br />
<br />
Espero que les sirva bastante. Dudas y mejoras en los comentarios, saludos!]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[Actualización a Risus Nova 2.1.5]]></title>
			<link>https://phpost.es/tema-Tutorial-Actualizaci%C3%B3n-a-Risus-Nova-2-1-5</link>
			<pubDate>Fri, 10 Jul 2026 16:56:48 +0200</pubDate>
			<dc:creator><![CDATA[<a href="https://phpost.es/member.php?action=profile&uid=1">Tronlar</a>]]></dc:creator>
			<guid isPermaLink="false">https://phpost.es/tema-Tutorial-Actualizaci%C3%B3n-a-Risus-Nova-2-1-5</guid>
			<description><![CDATA[<span style="font-size: x-large;" class="mycode_size"><span style="color: #2980b9;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">Actualización a Risus Nova 2.1.5</span></span></span><br />
<br />
<span style="font-size: large;" class="mycode_size">Esta actualización incluye correcciones de seguridad y bugs (ver el <span style="font-weight: bold;" class="mycode_b">CHANGELOG</span> para el detalle completo).<br />
<span style="font-weight: bold;" class="mycode_b">No requiere ejecutar ninguna consulta SQL</span> — todos los cambios son de código (PHP, JS, CSS, plantillas).</span><br />
 <br />
<hr class="mycode_hr" />
<br />
<span style="font-size: x-large;" class="mycode_size"><span style="color: #c0392b;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">⚠ Antes de empezar (en ambos casos)</span></span></span><br />
<br />
<span style="font-size: large;" class="mycode_size">Haz un <span style="font-weight: bold;" class="mycode_b">backup</span> rápido, aunque sea de estos dos elementos:</span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size">Tu archivo de configuración (`config.inc.php`)</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Tu carpeta `files/` (avatares, fotos, adjuntos subidos por usuarios)</span><br />
</li>
</ul>
 <br />
<hr class="mycode_hr" />
<br />
<span style="font-size: x-large;" class="mycode_size"><span style="color: #2980b9;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">🆕 Si es una instalación nueva / demo</span></span></span><br />
 <br />
<ol type="1" class="mycode_list"><li><span style="font-size: large;" class="mycode_size">Sube todos los archivos nuevos.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">No sobrescribas:</span></span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size">`config.inc.php` — tiene tus credenciales de base de datos y configuración propia</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">`files/` — son los datos reales de tus usuarios (avatares, fotos, adjuntos)</span><br />
</li>
</ul>
</li>
<li><span style="font-size: large;" class="mycode_size">Vacía la caché de plantillas de Smarty — carpeta <span style="font-weight: bold;" class="mycode_b">cache/</span> en la raíz del proyecto — <span style="font-weight: bold;" class="mycode_b">vacía el contenido, no borres la carpeta</span>.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Prueba: login, ver un post, comentar, el chat en vivo, y alguna acción de moderación si tienes cuenta admin.</span><br />
</li>
</ol>
 <br />
<hr class="mycode_hr" />
<br />
<span style="font-size: x-large;" class="mycode_size"><span style="color: #2980b9;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">🔄 Si ya tienes Risus Nova funcionando (sitio en producción)</span></span></span><br />
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">No borres nada de tu servidor.</span> Simplemente reemplazá los archivos que cambiaron, uno por uno o todos juntos, sobre tu instalación actual. Ningún archivo nuevo necesita una tabla o columna nueva en tu base de datos.</span><br />
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Pasos:</span></span><br />
<ol type="1" class="mycode_list"><li><span style="font-size: large;" class="mycode_size">Descarga el paquete de actualización 2.1.5 desde la sección de <span style="font-weight: bold;" class="mycode_b">Demos y Descargas</span>.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Descomprímelo y sube los archivos <span style="font-weight: bold;" class="mycode_b">respetando la misma estructura de carpetas</span> que ya tienes en tu instalación, sobrescribiendo cada archivo existente.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Hay <span style="font-weight: bold;" class="mycode_b">dos archivos nuevos</span> que no reemplazan nada — se agregan:</span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size">`JBBCode/validators/QuoteAuthorValidator.php`</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">la carpeta completa `inc/ext/htmlpurifier/`</span><br />
</li>
</ul>
</li>
<li><span style="font-size: large;" class="mycode_size">Vacía la caché de Smarty (carpeta `cache/` en la raíz del proyecto, mismo paso que arriba).</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Prueba el sitio normalmente.</span><br />
</li>
</ol>
<br />
<span style="color: #e74c3c;" class="mycode_color"><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">⚠ No toques:</span></span></span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size">`config.inc.php`</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">`files/` (o donde tengas configurado el almacenamiento de subidas — si usás Cloudinary, tampoco cambia nada ahí)</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Tu base de datos — no hace falta ningún `ALTER TABLE` ni consulta manual</span><br />
</li>
</ul>
 <br />
<hr class="mycode_hr" />
<br />
<span style="font-size: x-large;" class="mycode_size"><span style="color: #2980b9;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">📁 Lista de archivos de esta actualización</span></span></span><br />
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Clases (`inc/class/`)</span></span><br />
 <br />
<div class="codeblock phpcodeblock"><div class="title">Código PHP:</div><div class="body"><div dir="ltr"><code><span style="color: #0000BB">c</span><span style="color: #007700">.</span><span style="color: #0000BB">core</span><span style="color: #007700">.</span><span style="color: #0000BB">php&nbsp;·&nbsp;c</span><span style="color: #007700">.</span><span style="color: #0000BB">cuenta</span><span style="color: #007700">.</span><span style="color: #0000BB">php&nbsp;·&nbsp;c</span><span style="color: #007700">.</span><span style="color: #0000BB">user</span><span style="color: #007700">.</span><span style="color: #0000BB">php&nbsp;·&nbsp;c</span><span style="color: #007700">.</span><span style="color: #0000BB">portal</span><span style="color: #007700">.</span><span style="color: #0000BB">php&nbsp;·&nbsp;c</span><span style="color: #007700">.</span><span style="color: #0000BB">posts</span><span style="color: #007700">.</span><span style="color: #0000BB">php&nbsp;·&nbsp;c</span><span style="color: #007700">.</span><span style="color: #0000BB">muro</span><span style="color: #007700">.</span><span style="color: #0000BB">php&nbsp;·&nbsp;c</span><span style="color: #007700">.</span><span style="color: #0000BB">mensajes</span><span style="color: #007700">.</span><span style="color: #0000BB">php&nbsp;·&nbsp;c</span><span style="color: #007700">.</span><span style="color: #0000BB">comunidades</span><span style="color: #007700">.</span><span style="color: #0000BB">php&nbsp;·&nbsp;c</span><span style="color: #007700">.</span><span style="color: #0000BB">monitor</span><span style="color: #007700">.</span><span style="color: #0000BB">php&nbsp;·&nbsp;c</span><span style="color: #007700">.</span><span style="color: #0000BB">actividad</span><span style="color: #007700">.</span><span style="color: #0000BB">php&nbsp;·&nbsp;c</span><span style="color: #007700">.</span><span style="color: #0000BB">upload</span><span style="color: #007700">.</span><span style="color: #0000BB">php&nbsp;·&nbsp;c</span><span style="color: #007700">.</span><span style="color: #0000BB">registro</span><span style="color: #007700">.</span><span style="color: #0000BB">php&nbsp;·&nbsp;c</span><span style="color: #007700">.</span><span style="color: #0000BB">premios</span><span style="color: #007700">.</span><span style="color: #0000BB">php&nbsp;<br /></span></code></div></div></div><br />
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Controladores AJAX (`inc/php/ajax`)</span></span><br />
 <br />
<div class="codeblock phpcodeblock"><div class="title">Código PHP:</div><div class="body"><div dir="ltr"><code><span style="color: #0000BB">ajax_files</span><span style="color: #007700">.</span><span style="color: #0000BB">php&nbsp;·&nbsp;ajax</span><span style="color: #007700">.</span><span style="color: #0000BB">admin</span><span style="color: #007700">.</span><span style="color: #0000BB">php&nbsp;·&nbsp;ajax</span><span style="color: #007700">.</span><span style="color: #0000BB">upload</span><span style="color: #007700">.</span><span style="color: #0000BB">php&nbsp;·&nbsp;ajax</span><span style="color: #007700">.</span><span style="color: #0000BB">moderacion</span><span style="color: #007700">.</span><span style="color: #0000BB">php&nbsp;·&nbsp;ajax</span><span style="color: #007700">.</span><span style="color: #0000BB">usuario</span><span style="color: #007700">.</span><span style="color: #0000BB">php&nbsp;·&nbsp;ajax</span><span style="color: #007700">.</span><span style="color: #0000BB">denuncia</span><span style="color: #007700">.</span><span style="color: #0000BB">php&nbsp;·&nbsp;ajax</span><span style="color: #007700">.</span><span style="color: #0000BB">registro</span><span style="color: #007700">.</span><span style="color: #0000BB">php&nbsp;·&nbsp;ajax</span><span style="color: #007700">.</span><span style="color: #0000BB">recover</span><span style="color: #007700">.</span><span style="color: #0000BB">php&nbsp;·&nbsp;ajax</span><span style="color: #007700">.</span><span style="color: #0000BB">mensajes</span><span style="color: #007700">.</span><span style="color: #0000BB">php&nbsp;·&nbsp;ajax</span><span style="color: #007700">.</span><span style="color: #0000BB">posts</span><span style="color: #007700">.</span><span style="color: #0000BB">php&nbsp;·&nbsp;ajax</span><span style="color: #007700">.</span><span style="color: #0000BB">comunidades</span><span style="color: #007700">.</span><span style="color: #0000BB">php&nbsp;·&nbsp;ajax</span><span style="color: #007700">.</span><span style="color: #0000BB">muro</span><span style="color: #007700">.</span><span style="color: #0000BB">php&nbsp;·&nbsp;ajax</span><span style="color: #007700">.</span><span style="color: #0000BB">perfil</span><span style="color: #007700">.</span><span style="color: #0000BB">php&nbsp;·&nbsp;ajax</span><span style="color: #007700">.</span><span style="color: #0000BB">comentario</span><span style="color: #007700">.</span><span style="color: #0000BB">php&nbsp;·&nbsp;ajax</span><span style="color: #007700">.</span><span style="color: #0000BB">chat</span><span style="color: #007700">.</span><span style="color: #0000BB">php&nbsp;·&nbsp;ajax</span><span style="color: #007700">.</span><span style="color: #0000BB">notificaciones</span><span style="color: #007700">.</span><span style="color: #0000BB">php&nbsp;·&nbsp;ajax</span><span style="color: #007700">.</span><span style="color: #0000BB">favoritos</span><span style="color: #007700">.</span><span style="color: #0000BB">php&nbsp;·&nbsp;ajax</span><span style="color: #007700">.</span><span style="color: #0000BB">bloqueos</span><span style="color: #007700">.</span><span style="color: #0000BB">php&nbsp;<br /></span></code></div></div></div><br />
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b"> PHP (`inc/php/`)</span></span><br />
 <br />
<div class="codeblock phpcodeblock"><div class="title">Código PHP:</div><div class="body"><div dir="ltr"><code><span style="color: #0000BB">·&nbsp;admin</span><span style="color: #007700">.</span><span style="color: #0000BB">php&nbsp;·&nbsp;retos</span><span style="color: #007700">.</span><span style="color: #0000BB">php&nbsp;·&nbsp;portal</span><span style="color: #007700">.</span><span style="color: #0000BB">php&nbsp;<br /></span></code></div></div></div><br />
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Extensiones (`inc/ext/`)</span></span><br />
 <br />
<div class="codeblock phpcodeblock"><div class="title">Código PHP:</div><div class="body"><div dir="ltr"><code><span style="color: #0000BB">QueryString</span><span style="color: #007700">.</span><span style="color: #0000BB">php&nbsp;·&nbsp;functions</span><span style="color: #007700">.</span><span style="color: #0000BB">php&nbsp;·&nbsp;bbcode_inc</span><span style="color: #007700">.</span><span style="color: #0000BB">php&nbsp;·&nbsp;geodata</span><span style="color: #007700">.</span><span style="color: #0000BB">php&nbsp;·&nbsp;datos</span><span style="color: #007700">.</span><span style="color: #0000BB">php&nbsp;·&nbsp;wysibbupload</span><span style="color: #007700">.</span><span style="color: #0000BB">php&nbsp;·&nbsp;iupload</span><span style="color: #007700">.</span><span style="color: #0000BB">php&nbsp;<br /></span></code></div></div></div><br />
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Raíz del proyecto</span></span><br />
 <br />
<div class="codeblock phpcodeblock"><div class="title">Código PHP:</div><div class="body"><div dir="ltr"><code><span style="color: #007700">.</span><span style="color: #0000BB">htaccess&nbsp;<br /></span></code></div></div></div><br />
<br />
<span style="font-size: large;" class="mycode_size"><span style="color: #27ae60;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">🆕 Nuevos (no reemplazan nada existente):</span></span></span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size">`JBBCode/validators/QuoteAuthorValidator.php`</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">`inc/ext/htmlpurifier/` (carpeta completa)</span><br />
</li>
</ul>
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">JavaScript (`themes/default/js/`)</span></span><br />
 <br />
<div class="codeblock phpcodeblock"><div class="title">Código PHP:</div><div class="body"><div dir="ltr"><code><span style="color: #0000BB">link</span><span style="color: #007700">-</span><span style="color: #0000BB">preview</span><span style="color: #007700">.</span><span style="color: #0000BB">js&nbsp;·&nbsp;portal</span><span style="color: #007700">.</span><span style="color: #0000BB">js&nbsp;·&nbsp;comunidades</span><span style="color: #007700">.</span><span style="color: #0000BB">js&nbsp;·&nbsp;cuenta</span><span style="color: #007700">.</span><span style="color: #0000BB">js&nbsp;<br /></span></code></div></div></div><br />
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Plantillas de página (`themes/default/templates/`)</span></span><br />
 <br />
<div class="codeblock phpcodeblock"><div class="title">Código PHP:</div><div class="body"><div dir="ltr"><code><span style="color: #0000BB">t</span><span style="color: #007700">.</span><span style="color: #0000BB">perfil</span><span style="color: #007700">.</span><span style="color: #0000BB">tpl&nbsp;·&nbsp;t</span><span style="color: #007700">.</span><span style="color: #0000BB">login</span><span style="color: #007700">.</span><span style="color: #0000BB">tpl&nbsp;<br /></span></code></div></div></div><br />
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Sections (`themes/default/templates/sections/`)</span></span><br />
 <br />
<div class="codeblock phpcodeblock"><div class="title">Código PHP:</div><div class="body"><div dir="ltr"><code><span style="color: #0000BB">logo</span><span style="color: #007700">.</span><span style="color: #0000BB">tpl&nbsp;<br /></span></code></div></div></div><br />
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Módulos (`themes/default/templates/modules/`)</span></span><br />
 <br />
<div class="codeblock phpcodeblock"><div class="title">Código PHP:</div><div class="body"><div dir="ltr"><code><span style="color: #0000BB">m</span><span style="color: #007700">.</span><span style="color: #0000BB">cuenta_perfil_me</span><span style="color: #007700">.</span><span style="color: #0000BB">tpl&nbsp;·&nbsp;m</span><span style="color: #007700">.</span><span style="color: #0000BB">home_last_posts</span><span style="color: #007700">.</span><span style="color: #0000BB">tpl&nbsp;·&nbsp;m</span><span style="color: #007700">.</span><span style="color: #0000BB">home_tendencias</span><span style="color: #007700">.</span><span style="color: #0000BB">tpl&nbsp;<br /></span></code></div></div></div><br />
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Módulos de admin (`themes/default/templates/admin_mods/`)</span></span><br />
 <br />
<div class="codeblock phpcodeblock"><div class="title">Código PHP:</div><div class="body"><div dir="ltr"><code><span style="color: #0000BB">m</span><span style="color: #007700">.</span><span style="color: #0000BB">admin_cats</span><span style="color: #007700">.</span><span style="color: #0000BB">tpl&nbsp;·&nbsp;m</span><span style="color: #007700">.</span><span style="color: #0000BB">admin_noticias</span><span style="color: #007700">.</span><span style="color: #0000BB">tpl&nbsp;<br /></span></code></div></div></div><br />
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">CSS</span></span><br />
<div class="codeblock phpcodeblock"><div class="title">Código PHP:</div><div class="body"><div dir="ltr"><code><span style="color: #0000BB">estilo</span><span style="color: #007700">.</span><span style="color: #0000BB">css&nbsp;</span><span style="color: #007700">(</span><span style="color: #0000BB">en&nbsp;</span><span style="color: #007700">`</span><span style="color: #DD0000">themes/default/</span><span style="color: #007700">`)&nbsp;</span><span style="color: #0000BB">·&nbsp;perfil</span><span style="color: #007700">.</span><span style="color: #0000BB">css&nbsp;</span><span style="color: #007700">(</span><span style="color: #0000BB">en&nbsp;</span><span style="color: #007700">`</span><span style="color: #DD0000">themes/default/css/</span><span style="color: #007700">`)&nbsp;<br /></span></code></div></div></div><hr class="mycode_hr" />
<br />
<span style="font-size: x-large;" class="mycode_size"><span style="color: #2980b9;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">Cambios más importantes de esta versión (resumen)</span></span></span><br />
 <ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size">Corregidas varias inyecciones SQL, incluyendo una explotable sin necesitar sesión.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Cerrado un hallazgo de borrado arbitrario de archivos en el recorte de avatar.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Agregado un sanitizador HTML (HTMLPurifier) para el contenido del editor CKEditor en posts y comentarios, que antes se guardaba sin filtrar.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Corregidos varios Fatal Error que rompían el registro y la recuperación de contraseña por email.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Numerosos bugs menores de PHP 8, permisos de acceso y consistencia.</span><br />
</li>
</ul>
<br />
<span style="font-size: large;" class="mycode_size">Ver el <span style="font-weight: bold;" class="mycode_b">CHANGELOG</span> completo para el detalle entrada por entrada.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">phpost.es/descargas/CHANGELOG.html</span></span>]]></description>
			<content:encoded><![CDATA[<span style="font-size: x-large;" class="mycode_size"><span style="color: #2980b9;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">Actualización a Risus Nova 2.1.5</span></span></span><br />
<br />
<span style="font-size: large;" class="mycode_size">Esta actualización incluye correcciones de seguridad y bugs (ver el <span style="font-weight: bold;" class="mycode_b">CHANGELOG</span> para el detalle completo).<br />
<span style="font-weight: bold;" class="mycode_b">No requiere ejecutar ninguna consulta SQL</span> — todos los cambios son de código (PHP, JS, CSS, plantillas).</span><br />
 <br />
<hr class="mycode_hr" />
<br />
<span style="font-size: x-large;" class="mycode_size"><span style="color: #c0392b;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">⚠ Antes de empezar (en ambos casos)</span></span></span><br />
<br />
<span style="font-size: large;" class="mycode_size">Haz un <span style="font-weight: bold;" class="mycode_b">backup</span> rápido, aunque sea de estos dos elementos:</span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size">Tu archivo de configuración (`config.inc.php`)</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Tu carpeta `files/` (avatares, fotos, adjuntos subidos por usuarios)</span><br />
</li>
</ul>
 <br />
<hr class="mycode_hr" />
<br />
<span style="font-size: x-large;" class="mycode_size"><span style="color: #2980b9;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">🆕 Si es una instalación nueva / demo</span></span></span><br />
 <br />
<ol type="1" class="mycode_list"><li><span style="font-size: large;" class="mycode_size">Sube todos los archivos nuevos.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">No sobrescribas:</span></span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size">`config.inc.php` — tiene tus credenciales de base de datos y configuración propia</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">`files/` — son los datos reales de tus usuarios (avatares, fotos, adjuntos)</span><br />
</li>
</ul>
</li>
<li><span style="font-size: large;" class="mycode_size">Vacía la caché de plantillas de Smarty — carpeta <span style="font-weight: bold;" class="mycode_b">cache/</span> en la raíz del proyecto — <span style="font-weight: bold;" class="mycode_b">vacía el contenido, no borres la carpeta</span>.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Prueba: login, ver un post, comentar, el chat en vivo, y alguna acción de moderación si tienes cuenta admin.</span><br />
</li>
</ol>
 <br />
<hr class="mycode_hr" />
<br />
<span style="font-size: x-large;" class="mycode_size"><span style="color: #2980b9;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">🔄 Si ya tienes Risus Nova funcionando (sitio en producción)</span></span></span><br />
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">No borres nada de tu servidor.</span> Simplemente reemplazá los archivos que cambiaron, uno por uno o todos juntos, sobre tu instalación actual. Ningún archivo nuevo necesita una tabla o columna nueva en tu base de datos.</span><br />
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Pasos:</span></span><br />
<ol type="1" class="mycode_list"><li><span style="font-size: large;" class="mycode_size">Descarga el paquete de actualización 2.1.5 desde la sección de <span style="font-weight: bold;" class="mycode_b">Demos y Descargas</span>.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Descomprímelo y sube los archivos <span style="font-weight: bold;" class="mycode_b">respetando la misma estructura de carpetas</span> que ya tienes en tu instalación, sobrescribiendo cada archivo existente.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Hay <span style="font-weight: bold;" class="mycode_b">dos archivos nuevos</span> que no reemplazan nada — se agregan:</span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size">`JBBCode/validators/QuoteAuthorValidator.php`</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">la carpeta completa `inc/ext/htmlpurifier/`</span><br />
</li>
</ul>
</li>
<li><span style="font-size: large;" class="mycode_size">Vacía la caché de Smarty (carpeta `cache/` en la raíz del proyecto, mismo paso que arriba).</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Prueba el sitio normalmente.</span><br />
</li>
</ol>
<br />
<span style="color: #e74c3c;" class="mycode_color"><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">⚠ No toques:</span></span></span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size">`config.inc.php`</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">`files/` (o donde tengas configurado el almacenamiento de subidas — si usás Cloudinary, tampoco cambia nada ahí)</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Tu base de datos — no hace falta ningún `ALTER TABLE` ni consulta manual</span><br />
</li>
</ul>
 <br />
<hr class="mycode_hr" />
<br />
<span style="font-size: x-large;" class="mycode_size"><span style="color: #2980b9;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">📁 Lista de archivos de esta actualización</span></span></span><br />
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Clases (`inc/class/`)</span></span><br />
 <br />
<div class="codeblock phpcodeblock"><div class="title">Código PHP:</div><div class="body"><div dir="ltr"><code><span style="color: #0000BB">c</span><span style="color: #007700">.</span><span style="color: #0000BB">core</span><span style="color: #007700">.</span><span style="color: #0000BB">php&nbsp;·&nbsp;c</span><span style="color: #007700">.</span><span style="color: #0000BB">cuenta</span><span style="color: #007700">.</span><span style="color: #0000BB">php&nbsp;·&nbsp;c</span><span style="color: #007700">.</span><span style="color: #0000BB">user</span><span style="color: #007700">.</span><span style="color: #0000BB">php&nbsp;·&nbsp;c</span><span style="color: #007700">.</span><span style="color: #0000BB">portal</span><span style="color: #007700">.</span><span style="color: #0000BB">php&nbsp;·&nbsp;c</span><span style="color: #007700">.</span><span style="color: #0000BB">posts</span><span style="color: #007700">.</span><span style="color: #0000BB">php&nbsp;·&nbsp;c</span><span style="color: #007700">.</span><span style="color: #0000BB">muro</span><span style="color: #007700">.</span><span style="color: #0000BB">php&nbsp;·&nbsp;c</span><span style="color: #007700">.</span><span style="color: #0000BB">mensajes</span><span style="color: #007700">.</span><span style="color: #0000BB">php&nbsp;·&nbsp;c</span><span style="color: #007700">.</span><span style="color: #0000BB">comunidades</span><span style="color: #007700">.</span><span style="color: #0000BB">php&nbsp;·&nbsp;c</span><span style="color: #007700">.</span><span style="color: #0000BB">monitor</span><span style="color: #007700">.</span><span style="color: #0000BB">php&nbsp;·&nbsp;c</span><span style="color: #007700">.</span><span style="color: #0000BB">actividad</span><span style="color: #007700">.</span><span style="color: #0000BB">php&nbsp;·&nbsp;c</span><span style="color: #007700">.</span><span style="color: #0000BB">upload</span><span style="color: #007700">.</span><span style="color: #0000BB">php&nbsp;·&nbsp;c</span><span style="color: #007700">.</span><span style="color: #0000BB">registro</span><span style="color: #007700">.</span><span style="color: #0000BB">php&nbsp;·&nbsp;c</span><span style="color: #007700">.</span><span style="color: #0000BB">premios</span><span style="color: #007700">.</span><span style="color: #0000BB">php&nbsp;<br /></span></code></div></div></div><br />
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Controladores AJAX (`inc/php/ajax`)</span></span><br />
 <br />
<div class="codeblock phpcodeblock"><div class="title">Código PHP:</div><div class="body"><div dir="ltr"><code><span style="color: #0000BB">ajax_files</span><span style="color: #007700">.</span><span style="color: #0000BB">php&nbsp;·&nbsp;ajax</span><span style="color: #007700">.</span><span style="color: #0000BB">admin</span><span style="color: #007700">.</span><span style="color: #0000BB">php&nbsp;·&nbsp;ajax</span><span style="color: #007700">.</span><span style="color: #0000BB">upload</span><span style="color: #007700">.</span><span style="color: #0000BB">php&nbsp;·&nbsp;ajax</span><span style="color: #007700">.</span><span style="color: #0000BB">moderacion</span><span style="color: #007700">.</span><span style="color: #0000BB">php&nbsp;·&nbsp;ajax</span><span style="color: #007700">.</span><span style="color: #0000BB">usuario</span><span style="color: #007700">.</span><span style="color: #0000BB">php&nbsp;·&nbsp;ajax</span><span style="color: #007700">.</span><span style="color: #0000BB">denuncia</span><span style="color: #007700">.</span><span style="color: #0000BB">php&nbsp;·&nbsp;ajax</span><span style="color: #007700">.</span><span style="color: #0000BB">registro</span><span style="color: #007700">.</span><span style="color: #0000BB">php&nbsp;·&nbsp;ajax</span><span style="color: #007700">.</span><span style="color: #0000BB">recover</span><span style="color: #007700">.</span><span style="color: #0000BB">php&nbsp;·&nbsp;ajax</span><span style="color: #007700">.</span><span style="color: #0000BB">mensajes</span><span style="color: #007700">.</span><span style="color: #0000BB">php&nbsp;·&nbsp;ajax</span><span style="color: #007700">.</span><span style="color: #0000BB">posts</span><span style="color: #007700">.</span><span style="color: #0000BB">php&nbsp;·&nbsp;ajax</span><span style="color: #007700">.</span><span style="color: #0000BB">comunidades</span><span style="color: #007700">.</span><span style="color: #0000BB">php&nbsp;·&nbsp;ajax</span><span style="color: #007700">.</span><span style="color: #0000BB">muro</span><span style="color: #007700">.</span><span style="color: #0000BB">php&nbsp;·&nbsp;ajax</span><span style="color: #007700">.</span><span style="color: #0000BB">perfil</span><span style="color: #007700">.</span><span style="color: #0000BB">php&nbsp;·&nbsp;ajax</span><span style="color: #007700">.</span><span style="color: #0000BB">comentario</span><span style="color: #007700">.</span><span style="color: #0000BB">php&nbsp;·&nbsp;ajax</span><span style="color: #007700">.</span><span style="color: #0000BB">chat</span><span style="color: #007700">.</span><span style="color: #0000BB">php&nbsp;·&nbsp;ajax</span><span style="color: #007700">.</span><span style="color: #0000BB">notificaciones</span><span style="color: #007700">.</span><span style="color: #0000BB">php&nbsp;·&nbsp;ajax</span><span style="color: #007700">.</span><span style="color: #0000BB">favoritos</span><span style="color: #007700">.</span><span style="color: #0000BB">php&nbsp;·&nbsp;ajax</span><span style="color: #007700">.</span><span style="color: #0000BB">bloqueos</span><span style="color: #007700">.</span><span style="color: #0000BB">php&nbsp;<br /></span></code></div></div></div><br />
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b"> PHP (`inc/php/`)</span></span><br />
 <br />
<div class="codeblock phpcodeblock"><div class="title">Código PHP:</div><div class="body"><div dir="ltr"><code><span style="color: #0000BB">·&nbsp;admin</span><span style="color: #007700">.</span><span style="color: #0000BB">php&nbsp;·&nbsp;retos</span><span style="color: #007700">.</span><span style="color: #0000BB">php&nbsp;·&nbsp;portal</span><span style="color: #007700">.</span><span style="color: #0000BB">php&nbsp;<br /></span></code></div></div></div><br />
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Extensiones (`inc/ext/`)</span></span><br />
 <br />
<div class="codeblock phpcodeblock"><div class="title">Código PHP:</div><div class="body"><div dir="ltr"><code><span style="color: #0000BB">QueryString</span><span style="color: #007700">.</span><span style="color: #0000BB">php&nbsp;·&nbsp;functions</span><span style="color: #007700">.</span><span style="color: #0000BB">php&nbsp;·&nbsp;bbcode_inc</span><span style="color: #007700">.</span><span style="color: #0000BB">php&nbsp;·&nbsp;geodata</span><span style="color: #007700">.</span><span style="color: #0000BB">php&nbsp;·&nbsp;datos</span><span style="color: #007700">.</span><span style="color: #0000BB">php&nbsp;·&nbsp;wysibbupload</span><span style="color: #007700">.</span><span style="color: #0000BB">php&nbsp;·&nbsp;iupload</span><span style="color: #007700">.</span><span style="color: #0000BB">php&nbsp;<br /></span></code></div></div></div><br />
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Raíz del proyecto</span></span><br />
 <br />
<div class="codeblock phpcodeblock"><div class="title">Código PHP:</div><div class="body"><div dir="ltr"><code><span style="color: #007700">.</span><span style="color: #0000BB">htaccess&nbsp;<br /></span></code></div></div></div><br />
<br />
<span style="font-size: large;" class="mycode_size"><span style="color: #27ae60;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">🆕 Nuevos (no reemplazan nada existente):</span></span></span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size">`JBBCode/validators/QuoteAuthorValidator.php`</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">`inc/ext/htmlpurifier/` (carpeta completa)</span><br />
</li>
</ul>
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">JavaScript (`themes/default/js/`)</span></span><br />
 <br />
<div class="codeblock phpcodeblock"><div class="title">Código PHP:</div><div class="body"><div dir="ltr"><code><span style="color: #0000BB">link</span><span style="color: #007700">-</span><span style="color: #0000BB">preview</span><span style="color: #007700">.</span><span style="color: #0000BB">js&nbsp;·&nbsp;portal</span><span style="color: #007700">.</span><span style="color: #0000BB">js&nbsp;·&nbsp;comunidades</span><span style="color: #007700">.</span><span style="color: #0000BB">js&nbsp;·&nbsp;cuenta</span><span style="color: #007700">.</span><span style="color: #0000BB">js&nbsp;<br /></span></code></div></div></div><br />
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Plantillas de página (`themes/default/templates/`)</span></span><br />
 <br />
<div class="codeblock phpcodeblock"><div class="title">Código PHP:</div><div class="body"><div dir="ltr"><code><span style="color: #0000BB">t</span><span style="color: #007700">.</span><span style="color: #0000BB">perfil</span><span style="color: #007700">.</span><span style="color: #0000BB">tpl&nbsp;·&nbsp;t</span><span style="color: #007700">.</span><span style="color: #0000BB">login</span><span style="color: #007700">.</span><span style="color: #0000BB">tpl&nbsp;<br /></span></code></div></div></div><br />
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Sections (`themes/default/templates/sections/`)</span></span><br />
 <br />
<div class="codeblock phpcodeblock"><div class="title">Código PHP:</div><div class="body"><div dir="ltr"><code><span style="color: #0000BB">logo</span><span style="color: #007700">.</span><span style="color: #0000BB">tpl&nbsp;<br /></span></code></div></div></div><br />
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Módulos (`themes/default/templates/modules/`)</span></span><br />
 <br />
<div class="codeblock phpcodeblock"><div class="title">Código PHP:</div><div class="body"><div dir="ltr"><code><span style="color: #0000BB">m</span><span style="color: #007700">.</span><span style="color: #0000BB">cuenta_perfil_me</span><span style="color: #007700">.</span><span style="color: #0000BB">tpl&nbsp;·&nbsp;m</span><span style="color: #007700">.</span><span style="color: #0000BB">home_last_posts</span><span style="color: #007700">.</span><span style="color: #0000BB">tpl&nbsp;·&nbsp;m</span><span style="color: #007700">.</span><span style="color: #0000BB">home_tendencias</span><span style="color: #007700">.</span><span style="color: #0000BB">tpl&nbsp;<br /></span></code></div></div></div><br />
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Módulos de admin (`themes/default/templates/admin_mods/`)</span></span><br />
 <br />
<div class="codeblock phpcodeblock"><div class="title">Código PHP:</div><div class="body"><div dir="ltr"><code><span style="color: #0000BB">m</span><span style="color: #007700">.</span><span style="color: #0000BB">admin_cats</span><span style="color: #007700">.</span><span style="color: #0000BB">tpl&nbsp;·&nbsp;m</span><span style="color: #007700">.</span><span style="color: #0000BB">admin_noticias</span><span style="color: #007700">.</span><span style="color: #0000BB">tpl&nbsp;<br /></span></code></div></div></div><br />
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">CSS</span></span><br />
<div class="codeblock phpcodeblock"><div class="title">Código PHP:</div><div class="body"><div dir="ltr"><code><span style="color: #0000BB">estilo</span><span style="color: #007700">.</span><span style="color: #0000BB">css&nbsp;</span><span style="color: #007700">(</span><span style="color: #0000BB">en&nbsp;</span><span style="color: #007700">`</span><span style="color: #DD0000">themes/default/</span><span style="color: #007700">`)&nbsp;</span><span style="color: #0000BB">·&nbsp;perfil</span><span style="color: #007700">.</span><span style="color: #0000BB">css&nbsp;</span><span style="color: #007700">(</span><span style="color: #0000BB">en&nbsp;</span><span style="color: #007700">`</span><span style="color: #DD0000">themes/default/css/</span><span style="color: #007700">`)&nbsp;<br /></span></code></div></div></div><hr class="mycode_hr" />
<br />
<span style="font-size: x-large;" class="mycode_size"><span style="color: #2980b9;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">Cambios más importantes de esta versión (resumen)</span></span></span><br />
 <ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size">Corregidas varias inyecciones SQL, incluyendo una explotable sin necesitar sesión.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Cerrado un hallazgo de borrado arbitrario de archivos en el recorte de avatar.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Agregado un sanitizador HTML (HTMLPurifier) para el contenido del editor CKEditor en posts y comentarios, que antes se guardaba sin filtrar.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Corregidos varios Fatal Error que rompían el registro y la recuperación de contraseña por email.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Numerosos bugs menores de PHP 8, permisos de acceso y consistencia.</span><br />
</li>
</ul>
<br />
<span style="font-size: large;" class="mycode_size">Ver el <span style="font-weight: bold;" class="mycode_b">CHANGELOG</span> completo para el detalle entrada por entrada.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">phpost.es/descargas/CHANGELOG.html</span></span>]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[Tienda de Puntos v1.5]]></title>
			<link>https://phpost.es/tema-COMPLEMENTOS-Tienda-de-Puntos-v1-5</link>
			<pubDate>Thu, 09 Jul 2026 21:12:28 +0200</pubDate>
			<dc:creator><![CDATA[<a href="https://phpost.es/member.php?action=profile&uid=1">Tronlar</a>]]></dc:creator>
			<guid isPermaLink="false">https://phpost.es/tema-COMPLEMENTOS-Tienda-de-Puntos-v1-5</guid>
			<description><![CDATA[<div style="text-align: center;" class="mycode_align"><span style="color: #2980b9;" class="mycode_color"><span style="font-size: x-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Tienda de Puntos v1.5</span></span></span><br />
<span style="font-size: large;" class="mycode_size">Actualización del módulo de Tienda de Puntos para Risus Nova 2.0 — PHPost</span></div>
<hr class="mycode_hr" />
<span style="font-size: large;" class="mycode_size">Complemento para <span style="font-weight: bold;" class="mycode_b">Risus Nova 2.0</span>: la <span style="font-weight: bold;" class="mycode_b">Tienda de Puntos</span>. Permite a los usuarios gastar sus puntos acumulados en mejoras para su perfil y sus posts.</span><br />
<hr class="mycode_hr" />
<br />
<span style="color: #e74c3c;" class="mycode_color"><span style="font-size: x-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">🆕 Novedades en la v1.5</span></span></span><br />
 <ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Regalar puntos a otro usuario</span> — desde la propia tienda, indicando el nombre del destinatario, una cantidad y un mensaje opcional</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Regalar artículos de la tienda</span> — Marco de Avatar, Medalla y Rango se pueden comprar para regalárselos a otro usuario</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Rango temporal o permanente</span> — nuevo tipo de artículo configurable: el admin elige a qué rango da acceso y durante cuántos días (0 = permanente). Al caducar, el usuario vuelve automáticamente a su rango anterior</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Nueva sección "Mis últimos regalos" en la tienda, con lo enviado y recibido</span><br />
</li>
</ul>
<br />
<span style="color: #e74c3c;" class="mycode_color"><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">⚠️ ¿Vienes de la v1.0?</span></span></span><br />
<span style="font-size: large;" class="mycode_size">No hace falta reinstalar desde cero. Solo tienes que:</span><br />
 <br />
<ol type="1" class="mycode_list"><li><span style="font-size: large;" class="mycode_size">Ejecutar el archivo <span style="font-weight: bold;" class="mycode_b">MIGRACION_si_ya_tenias_instalada_v1.0.sql</span> una vez, en phpMyAdmin</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Sustituir estos 4 archivos por los de esta versión:</span><br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>inc/class/c.tienda.php<br />
inc/php/tienda.php<br />
themes/default/templates/modules/tienda/t.tienda.tpl<br />
themes/default/templates/modules/tienda/t.tienda.admin.form.tpl</code></div></div></li>
<li><span style="font-size: large;" class="mycode_size">Borrar la caché (<span style="font-weight: bold;" class="mycode_b">/cache/</span>)</span><br />
</li>
</ol>
<br />
<span style="font-size: large;" class="mycode_size">Los archivos <span style="font-weight: bold;" class="mycode_b">t.tienda.historial.tpl</span>, <span style="font-weight: bold;" class="mycode_b">t.tienda.admin.tpl</span> y <span style="font-weight: bold;" class="mycode_b">tienda.css</span> no han cambiado, no hace falta volver a subirlos.</span><br />
<hr class="mycode_hr" />
<br />
<span style="color: #2980b9;" class="mycode_color"><span style="font-size: x-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">🛒 ¿Qué incluye?</span></span></span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Cambio de nick</span> — Los usuarios pueden cambiar su nombre una vez cada 30 días.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Título personalizado</span> — Un texto exclusivo que aparece bajo el nick en comentarios y perfil.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Color de nombre</span> — Personaliza el color del nick con cualquier color hexadecimal.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Marco de avatar</span> — Añade un marco especial alrededor del avatar.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Destacar post 24h</span> — El post aparece destacado en la portada durante 24 horas.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Post fijado 48h</span> — El post queda fijado en su categoría durante 48 horas.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Subir de rango</span> — Sube al siguiente rango sin necesidad de acumular más puntos.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Medallas</span> — Obtén medallas exclusivas para el perfil.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Rango temporal o permanente</span> — accede a un rango específico configurado por el admin, con o sin fecha de caducidad.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Regalos</span> — regala puntos o artículos de la tienda a otros usuarios.</span><br />
</li>
</ul>
<hr class="mycode_hr" />
<span style="color: #2980b9;" class="mycode_color"><span style="font-size: x-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">📋 Requisitos</span></span></span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Risus Nova 2.0</span> instalado y funcionando</span><br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><span style="font-size: large;" class="mycode_size">PHP 8.0+</span></span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">MySQL 5.7+</span> / <span style="font-weight: bold;" class="mycode_b">MariaDB 10.4+</span></span><br />
</li>
</ul>
<hr class="mycode_hr" />
<span style="font-size: x-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b"><span style="color: #2196f3;" class="mycode_color">🛠️ Instalación (desde cero)</span></span></span><br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Paso 1 — Ejecutar el instalador</span></span><br />
<span style="font-size: large;" class="mycode_size">Sube la carpeta <span style="font-weight: bold;" class="mycode_b">install/</span> del ZIP a la raíz de tu sitio y accede a:</span><br />
 <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>Registrate o inicia tu sesión para ver este contenido</code></div></div><span style="font-size: large;" class="mycode_size">Pulsa <span style="font-weight: bold;" class="mycode_b">Instalar ahora</span>. El instalador creará automáticamente:</span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size">Tabla <span style="font-weight: bold;" class="mycode_b">w_tienda</span> — catálogo de artículos</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Tabla <span style="font-weight: bold;" class="mycode_b">w_tienda_compras</span> — historial de compras</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Tabla <span style="font-weight: bold;" class="mycode_b">w_tienda_regalos</span> — historial de regalos de puntos</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Columnas nuevas en <span style="font-weight: bold;" class="mycode_b">u_miembros</span>: user_title, user_name_color, user_avatar_frame, user_rango_original, user_rango_expira</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Columnas nuevas en <span style="font-weight: bold;" class="mycode_b">p_posts</span>: post_featured, post_sticky_until</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">9 artículos de ejemplo con precios predefinidos</span><br />
</li>
</ul>
<span style="color: #2980b9;" class="mycode_color"><span style="font-size: x-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">⚠️ Elimina la carpeta install/ del servidor cuando termine.</span></span></span><br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Paso 2 — Subir los archivos</span></span><br />
 <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>inc/class/c.tienda.php&nbsp;&nbsp;&nbsp;&nbsp; →&nbsp;&nbsp;inc/class/<br />
inc/php/tienda.php&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; →&nbsp;&nbsp;inc/php/<br />
themes/default/css/tienda.css&nbsp;&nbsp;→&nbsp;&nbsp;themes/default/css/<br />
themes/default/t.tienda.tpl&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;→&nbsp;&nbsp;themes/default/templates/<br />
themes/default/t.tienda.historial.tpl&nbsp;&nbsp;→&nbsp;&nbsp;themes/default/templates/<br />
themes/default/t.tienda.admin.tpl&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;→&nbsp;&nbsp;themes/default/templates/<br />
themes/default/t.tienda.admin.form.tpl →&nbsp;&nbsp;themes/default/templates/</code></div></div><span style="color: #2980b9;" class="mycode_color"><span style="font-size: x-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Paso 3 — Añadir el CSS en el header</span></span></span><br />
<span style="font-size: large;" class="mycode_size">Abre <span style="font-weight: bold;" class="mycode_b">themes/default/templates/sections/main_header.tpl</span> y añade esta línea junto al resto de CSS:</span><br />
 <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>&lt;link href="{&#36;tsConfig.css}/tienda.css" rel="stylesheet" type="text/css"&gt;</code></div></div><span style="color: #2980b9;" class="mycode_color"><span style="font-size: x-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Paso 4 — Añadir el enlace en el menú</span></span></span><br />
<span style="font-size: large;" class="mycode_size">Abre <span style="font-weight: bold;" class="mycode_b">themes/default/templates/sections/head_menu.tpl</span> y añade este elemento en el menú principal:</span><br />
 <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>&lt;li class="tabbed {if &#36;tsPage == 'tienda'}here{/if}" id="tabbedtienda"&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;a title="Ir a la Tienda" onclick="menu('tienda', this.href); return false;" href="{&#36;tsConfig.url}/tienda/"&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;i class="fa-solid fa-store"&gt;&lt;/i&gt; Tienda<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;/a&gt;<br />
&lt;/li&gt;</code></div></div><span style="color: #2980b9;" class="mycode_color"><span style="font-size: x-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Paso 5 — Borrar la caché</span></span></span><br />
<span style="font-size: large;" class="mycode_size">Borra el contenido de la carpeta <span style="font-weight: bold;" class="mycode_b">/cache/</span> desde el panel de administración o desde el gestor de archivos del hosting.</span><br />
<hr class="mycode_hr" />
<span style="font-size: x-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b"><span style="color: #2196f3;" class="mycode_color">⚙️ Gestionar los artículos</span></span></span><br />
<span style="font-size: large;" class="mycode_size">Accede como administrador a <span style="font-weight: bold;" class="mycode_b">tudominio.com/tienda/?action=admin</span> para:</span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size">Crear nuevos artículos, incluyendo rangos temporales/permanentes</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Editar precios y descripciones</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Activar o desactivar artículos</span><br />
</li>
</ul>
<hr class="mycode_hr" />
<span style="color: #e74c3c;" class="mycode_color"><span style="font-size: x-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">🗑️ Desinstalar</span></span></span><br />
<span style="font-size: large;" class="mycode_size">Si quieres eliminar el complemento, ejecuta esto en <span style="font-weight: bold;" class="mycode_b">phpMyAdmin</span>:</span><br />
 <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>DROP TABLE IF EXISTS w_tienda;<br />
DROP TABLE IF EXISTS w_tienda_compras;<br />
DROP TABLE IF EXISTS w_tienda_regalos;<br />
ALTER TABLE u_miembros DROP COLUMN user_title;<br />
ALTER TABLE u_miembros DROP COLUMN user_name_color;<br />
ALTER TABLE u_miembros DROP COLUMN user_avatar_frame;<br />
ALTER TABLE u_miembros DROP COLUMN user_rango_original;<br />
ALTER TABLE u_miembros DROP COLUMN user_rango_expira;<br />
ALTER TABLE p_posts DROP COLUMN post_featured;<br />
ALTER TABLE p_posts DROP COLUMN post_sticky_until;</code></div></div><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Y elimina los archivos subidos en el paso 2.</span></span><br />
<hr class="mycode_hr" />
<br />
<span style="color: #2980b9;" class="mycode_color"><span style="font-size: x-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Capturas</span></span></span><br />
<div style="text-align: center;" class="mycode_align"><img src="https://i.imgur.com/LWdwRY3.png" loading="lazy"  alt="[Imagen: LWdwRY3.png]" class="mycode_img img-responsive" /><br />
<img src="https://i.imgur.com/4h6JOfl.png" loading="lazy"  alt="[Imagen: 4h6JOfl.png]" class="mycode_img img-responsive" /><br />
<img src="https://i.imgur.com/ynt9TT6.png" loading="lazy"  alt="[Imagen: ynt9TT6.png]" class="mycode_img img-responsive" /></div>
 <br />
<div style="text-align: center;" class="mycode_align"><span style="color: #e74c3c;" class="mycode_color"><span style="font-size: x-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Descarga</span></span></span><br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Mediafire</span></span><br />
<a href="http://Registrate%20o%20inicia%20tu%20sesión%20para%20ver%20este%20contenido" target="_blank" rel="noopener" class="mycode_url">http://Registrate o inicia tu sesión par... contenido</a><br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Google Drive</span></span><br />
<a href="http://Registrate%20o%20inicia%20tu%20sesión%20para%20ver%20este%20contenido" target="_blank" rel="noopener" class="mycode_url">http://Registrate o inicia tu sesión par... contenido</a><br />
<span style="color: #2980b9;" class="mycode_color"><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">¿Tienes dudas o encuentras algún problema? Déjalo en los comentarios.</span></span></span></div>]]></description>
			<content:encoded><![CDATA[<div style="text-align: center;" class="mycode_align"><span style="color: #2980b9;" class="mycode_color"><span style="font-size: x-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Tienda de Puntos v1.5</span></span></span><br />
<span style="font-size: large;" class="mycode_size">Actualización del módulo de Tienda de Puntos para Risus Nova 2.0 — PHPost</span></div>
<hr class="mycode_hr" />
<span style="font-size: large;" class="mycode_size">Complemento para <span style="font-weight: bold;" class="mycode_b">Risus Nova 2.0</span>: la <span style="font-weight: bold;" class="mycode_b">Tienda de Puntos</span>. Permite a los usuarios gastar sus puntos acumulados en mejoras para su perfil y sus posts.</span><br />
<hr class="mycode_hr" />
<br />
<span style="color: #e74c3c;" class="mycode_color"><span style="font-size: x-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">🆕 Novedades en la v1.5</span></span></span><br />
 <ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Regalar puntos a otro usuario</span> — desde la propia tienda, indicando el nombre del destinatario, una cantidad y un mensaje opcional</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Regalar artículos de la tienda</span> — Marco de Avatar, Medalla y Rango se pueden comprar para regalárselos a otro usuario</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Rango temporal o permanente</span> — nuevo tipo de artículo configurable: el admin elige a qué rango da acceso y durante cuántos días (0 = permanente). Al caducar, el usuario vuelve automáticamente a su rango anterior</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Nueva sección "Mis últimos regalos" en la tienda, con lo enviado y recibido</span><br />
</li>
</ul>
<br />
<span style="color: #e74c3c;" class="mycode_color"><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">⚠️ ¿Vienes de la v1.0?</span></span></span><br />
<span style="font-size: large;" class="mycode_size">No hace falta reinstalar desde cero. Solo tienes que:</span><br />
 <br />
<ol type="1" class="mycode_list"><li><span style="font-size: large;" class="mycode_size">Ejecutar el archivo <span style="font-weight: bold;" class="mycode_b">MIGRACION_si_ya_tenias_instalada_v1.0.sql</span> una vez, en phpMyAdmin</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Sustituir estos 4 archivos por los de esta versión:</span><br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>inc/class/c.tienda.php<br />
inc/php/tienda.php<br />
themes/default/templates/modules/tienda/t.tienda.tpl<br />
themes/default/templates/modules/tienda/t.tienda.admin.form.tpl</code></div></div></li>
<li><span style="font-size: large;" class="mycode_size">Borrar la caché (<span style="font-weight: bold;" class="mycode_b">/cache/</span>)</span><br />
</li>
</ol>
<br />
<span style="font-size: large;" class="mycode_size">Los archivos <span style="font-weight: bold;" class="mycode_b">t.tienda.historial.tpl</span>, <span style="font-weight: bold;" class="mycode_b">t.tienda.admin.tpl</span> y <span style="font-weight: bold;" class="mycode_b">tienda.css</span> no han cambiado, no hace falta volver a subirlos.</span><br />
<hr class="mycode_hr" />
<br />
<span style="color: #2980b9;" class="mycode_color"><span style="font-size: x-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">🛒 ¿Qué incluye?</span></span></span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Cambio de nick</span> — Los usuarios pueden cambiar su nombre una vez cada 30 días.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Título personalizado</span> — Un texto exclusivo que aparece bajo el nick en comentarios y perfil.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Color de nombre</span> — Personaliza el color del nick con cualquier color hexadecimal.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Marco de avatar</span> — Añade un marco especial alrededor del avatar.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Destacar post 24h</span> — El post aparece destacado en la portada durante 24 horas.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Post fijado 48h</span> — El post queda fijado en su categoría durante 48 horas.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Subir de rango</span> — Sube al siguiente rango sin necesidad de acumular más puntos.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Medallas</span> — Obtén medallas exclusivas para el perfil.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Rango temporal o permanente</span> — accede a un rango específico configurado por el admin, con o sin fecha de caducidad.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Regalos</span> — regala puntos o artículos de la tienda a otros usuarios.</span><br />
</li>
</ul>
<hr class="mycode_hr" />
<span style="color: #2980b9;" class="mycode_color"><span style="font-size: x-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">📋 Requisitos</span></span></span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Risus Nova 2.0</span> instalado y funcionando</span><br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><span style="font-size: large;" class="mycode_size">PHP 8.0+</span></span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">MySQL 5.7+</span> / <span style="font-weight: bold;" class="mycode_b">MariaDB 10.4+</span></span><br />
</li>
</ul>
<hr class="mycode_hr" />
<span style="font-size: x-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b"><span style="color: #2196f3;" class="mycode_color">🛠️ Instalación (desde cero)</span></span></span><br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Paso 1 — Ejecutar el instalador</span></span><br />
<span style="font-size: large;" class="mycode_size">Sube la carpeta <span style="font-weight: bold;" class="mycode_b">install/</span> del ZIP a la raíz de tu sitio y accede a:</span><br />
 <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>Registrate o inicia tu sesión para ver este contenido</code></div></div><span style="font-size: large;" class="mycode_size">Pulsa <span style="font-weight: bold;" class="mycode_b">Instalar ahora</span>. El instalador creará automáticamente:</span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size">Tabla <span style="font-weight: bold;" class="mycode_b">w_tienda</span> — catálogo de artículos</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Tabla <span style="font-weight: bold;" class="mycode_b">w_tienda_compras</span> — historial de compras</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Tabla <span style="font-weight: bold;" class="mycode_b">w_tienda_regalos</span> — historial de regalos de puntos</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Columnas nuevas en <span style="font-weight: bold;" class="mycode_b">u_miembros</span>: user_title, user_name_color, user_avatar_frame, user_rango_original, user_rango_expira</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Columnas nuevas en <span style="font-weight: bold;" class="mycode_b">p_posts</span>: post_featured, post_sticky_until</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">9 artículos de ejemplo con precios predefinidos</span><br />
</li>
</ul>
<span style="color: #2980b9;" class="mycode_color"><span style="font-size: x-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">⚠️ Elimina la carpeta install/ del servidor cuando termine.</span></span></span><br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Paso 2 — Subir los archivos</span></span><br />
 <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>inc/class/c.tienda.php&nbsp;&nbsp;&nbsp;&nbsp; →&nbsp;&nbsp;inc/class/<br />
inc/php/tienda.php&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; →&nbsp;&nbsp;inc/php/<br />
themes/default/css/tienda.css&nbsp;&nbsp;→&nbsp;&nbsp;themes/default/css/<br />
themes/default/t.tienda.tpl&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;→&nbsp;&nbsp;themes/default/templates/<br />
themes/default/t.tienda.historial.tpl&nbsp;&nbsp;→&nbsp;&nbsp;themes/default/templates/<br />
themes/default/t.tienda.admin.tpl&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;→&nbsp;&nbsp;themes/default/templates/<br />
themes/default/t.tienda.admin.form.tpl →&nbsp;&nbsp;themes/default/templates/</code></div></div><span style="color: #2980b9;" class="mycode_color"><span style="font-size: x-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Paso 3 — Añadir el CSS en el header</span></span></span><br />
<span style="font-size: large;" class="mycode_size">Abre <span style="font-weight: bold;" class="mycode_b">themes/default/templates/sections/main_header.tpl</span> y añade esta línea junto al resto de CSS:</span><br />
 <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>&lt;link href="{&#36;tsConfig.css}/tienda.css" rel="stylesheet" type="text/css"&gt;</code></div></div><span style="color: #2980b9;" class="mycode_color"><span style="font-size: x-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Paso 4 — Añadir el enlace en el menú</span></span></span><br />
<span style="font-size: large;" class="mycode_size">Abre <span style="font-weight: bold;" class="mycode_b">themes/default/templates/sections/head_menu.tpl</span> y añade este elemento en el menú principal:</span><br />
 <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>&lt;li class="tabbed {if &#36;tsPage == 'tienda'}here{/if}" id="tabbedtienda"&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;a title="Ir a la Tienda" onclick="menu('tienda', this.href); return false;" href="{&#36;tsConfig.url}/tienda/"&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;i class="fa-solid fa-store"&gt;&lt;/i&gt; Tienda<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;/a&gt;<br />
&lt;/li&gt;</code></div></div><span style="color: #2980b9;" class="mycode_color"><span style="font-size: x-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Paso 5 — Borrar la caché</span></span></span><br />
<span style="font-size: large;" class="mycode_size">Borra el contenido de la carpeta <span style="font-weight: bold;" class="mycode_b">/cache/</span> desde el panel de administración o desde el gestor de archivos del hosting.</span><br />
<hr class="mycode_hr" />
<span style="font-size: x-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b"><span style="color: #2196f3;" class="mycode_color">⚙️ Gestionar los artículos</span></span></span><br />
<span style="font-size: large;" class="mycode_size">Accede como administrador a <span style="font-weight: bold;" class="mycode_b">tudominio.com/tienda/?action=admin</span> para:</span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size">Crear nuevos artículos, incluyendo rangos temporales/permanentes</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Editar precios y descripciones</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Activar o desactivar artículos</span><br />
</li>
</ul>
<hr class="mycode_hr" />
<span style="color: #e74c3c;" class="mycode_color"><span style="font-size: x-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">🗑️ Desinstalar</span></span></span><br />
<span style="font-size: large;" class="mycode_size">Si quieres eliminar el complemento, ejecuta esto en <span style="font-weight: bold;" class="mycode_b">phpMyAdmin</span>:</span><br />
 <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>DROP TABLE IF EXISTS w_tienda;<br />
DROP TABLE IF EXISTS w_tienda_compras;<br />
DROP TABLE IF EXISTS w_tienda_regalos;<br />
ALTER TABLE u_miembros DROP COLUMN user_title;<br />
ALTER TABLE u_miembros DROP COLUMN user_name_color;<br />
ALTER TABLE u_miembros DROP COLUMN user_avatar_frame;<br />
ALTER TABLE u_miembros DROP COLUMN user_rango_original;<br />
ALTER TABLE u_miembros DROP COLUMN user_rango_expira;<br />
ALTER TABLE p_posts DROP COLUMN post_featured;<br />
ALTER TABLE p_posts DROP COLUMN post_sticky_until;</code></div></div><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Y elimina los archivos subidos en el paso 2.</span></span><br />
<hr class="mycode_hr" />
<br />
<span style="color: #2980b9;" class="mycode_color"><span style="font-size: x-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Capturas</span></span></span><br />
<div style="text-align: center;" class="mycode_align"><img src="https://i.imgur.com/LWdwRY3.png" loading="lazy"  alt="[Imagen: LWdwRY3.png]" class="mycode_img img-responsive" /><br />
<img src="https://i.imgur.com/4h6JOfl.png" loading="lazy"  alt="[Imagen: 4h6JOfl.png]" class="mycode_img img-responsive" /><br />
<img src="https://i.imgur.com/ynt9TT6.png" loading="lazy"  alt="[Imagen: ynt9TT6.png]" class="mycode_img img-responsive" /></div>
 <br />
<div style="text-align: center;" class="mycode_align"><span style="color: #e74c3c;" class="mycode_color"><span style="font-size: x-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Descarga</span></span></span><br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Mediafire</span></span><br />
<a href="http://Registrate%20o%20inicia%20tu%20sesión%20para%20ver%20este%20contenido" target="_blank" rel="noopener" class="mycode_url">http://Registrate o inicia tu sesión par... contenido</a><br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Google Drive</span></span><br />
<a href="http://Registrate%20o%20inicia%20tu%20sesión%20para%20ver%20este%20contenido" target="_blank" rel="noopener" class="mycode_url">http://Registrate o inicia tu sesión par... contenido</a><br />
<span style="color: #2980b9;" class="mycode_color"><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">¿Tienes dudas o encuentras algún problema? Déjalo en los comentarios.</span></span></span></div>]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[Risus Nova 2.1 - Cosas Que eE Visto]]></title>
			<link>https://phpost.es/tema-RESUELTO-Risus-Nova-2-1-Cosas-Que-eE-Visto</link>
			<pubDate>Thu, 09 Jul 2026 20:45:55 +0200</pubDate>
			<dc:creator><![CDATA[<a href="https://phpost.es/member.php?action=profile&uid=1547">carlos007r</a>]]></dc:creator>
			<guid isPermaLink="false">https://phpost.es/tema-RESUELTO-Risus-Nova-2-1-Cosas-Que-eE-Visto</guid>
			<description><![CDATA[Hola! estoy corriendo Risus Nova v2.1 en un entorno local con PHP 8.2.12 con ayuda de claude code y fuimos encontrando varios bugs? del core. Los reporto acá con la causa y el fix que aplicamos, por si sirve para una próxima actualización. Los divido por categoría.<br />
<br />
1.<span style="font-weight: bold;" class="mycode_b"> INCOMPATIBILIDADES CON PHP 8.x</span><br />
<br />
- Error 500 al guardar el perfil si se deja un checkbox "Me gustaría" sin marcar: en c.cuenta.php, se accede a &#36;_POST['g_'.&#36;i] sin verificar que exista. Los checkboxes no marcados no viajan en el POST, y en PHP 8.2 pasar null a una función que espera string es un TypeError fatal. Fix: &#36;_POST['g_'.&#36;i] ?? ''.<br />
<br />
- Error 500 al guardar "Sitio Web" con una URL válida: se usa la constante FILTER_FLAG_HOST_REQUIRED en filter_var(), eliminada en PHP 8. Fix: sacar ese tercer argumento.<br />
<br />
2. <span style="font-weight: bold;" class="mycode_b">URLs/REDIRECCIONES ROTAS EN INSTALACIONES EN SUBDIRECTORIO</span><br />
<br />
- Redirecciones de login (setLevel(), redirectTo() en c.core.php) arman la URL a mano sin anteponer &#36;this-&gt;settings['url'], así que en cualquier instalación que NO viva en la raíz del dominio (ej. midominio.com/foro/), termina redirigiendo a midominio.com/login/... (sin el subdirectorio) → 404.<br />
<br />
- Botones "Volver al listado" (/admin/news) y "Mover Posts" (/admin/cats) en el panel de admin usan location.href = '/admin/...' hardcodeado en las plantillas, mismo problema.<br />
<br />
- Ícono de RSS de "Últimos posts" en el home también hardcodea /rss/ultimos-post sin el prefijo.<br />
<br />
3. <span style="font-weight: bold;" class="mycode_b">BUGS DE LÓGICA / FUNCIONES INCOMPLETAS</span><br />
<br />
- /admin/creditos muestra la librería GD como N/A aunque esté instalada y funcionando: el bloque elseif(&#36;action=='creditos') de admin.php nunca asigna &#36;smarty-&gt;assign("tsVersion", &#36;tsAdmin-&gt;getVersions()).<br />
<br />
- Selects de país/estado/mes/año vacíos en /cuenta/perfil: el bloque que asigna esos datos en cuenta.php corre con if(empty(&#36;action)), pero la ruta real entra con &#36;action='perfil', así que nunca se ejecuta.<br />
<br />
- Faltan las provincias/estados de ~80 países en geodata.php (confirmado con República Dominicana, Islandia, Singapur, entre otros): el array &#36;estados[...] simplemente no los tiene cargados.<br />
<br />
- Selects "Fumo" y "Tomo alcohol" vacíos (sección "Cómo soy" del perfil): en datos.php solo existe el array combinado fumo_tomo, pero la plantilla busca fumo y alcohol por separado (no existen).<br />
<br />
- "Me gustaría" (checkboxes) no se mostraba en el perfil: typo en la plantilla, pide &#36;tsPData.gustaria/&#36;tsPerfil.p_gustaria en vez de .gustos/.p_gustos (el nombre real usado en toda la base de datos y el resto del código).<br />
<br />
- /retos/ da "No direct access." y luego error 500: tres bugs apilados. Falta la regla en .htaccess (las páginas hermanas como calendario/misiones/premios sí la tienen), el guard chequea una constante que no existe en ningún lado del código (TSCRIPT en vez de TS_HEADER), y después de rutear bien, llama a &#36;tsCore-&gt;setTitle(), un método que no existe en la clase.<br />
<br />
- muro.load_atta() (JS del muro) está sin terminar: recibe la URL de la foto/video adjunto al hacer click, pero nunca la usa, reemplaza el elemento clickeado por una imagen vacía o un string vacío, haciendo "desaparecer" la foto/video en vez de mostrarla en grande.<br />
<br />
- Avatar GIF animado se queda estático en todo el sitio: imagecreatefromgif() + imagejpeg() de GD solo puede leer/escribir UN cuadro, así que cualquier GIF que pase por el recorte/generación de miniaturas del avatar (c.upload.php) pierde la animación.<br />
<br />
- Imagen de fondo de perfil no se aplicaba nunca: typo de tipo MIME en la plantilla, &lt;style type="text/style"&gt; en vez de text/css. Por spec de HTML5 los navegadores ignoran por completo un &lt;style&gt; con type inválido, así que el background-image nunca se veía aunque la URL fuera correcta.<br />
<br />
- Portada de perfil no se mostraba en /mi/: el controlador (portal.php) solo carga &#36;tsPerfil condicionalmente (para el aviso de bienvenida a cuentas nuevas), nunca de forma incondicional para el resto de la página.<br />
<br />
- Al subir una foto de perfil inválida, el mensaje de error mostraba [object Object] en vez del texto real, porque el callback de éxito solo sabía manejar dos formatos de respuesta distintos y no el de error real del servidor.<br />
<br />
- "Subir por URL" para avatar rechazaba links de imagen con ?token=... (típico en CDNs como *****): la validación de extensión de archivo no ignoraba el query string de la URL.<br />
<br />
- Videos de YouTube embebidos en el cuerpo de un post se comportaban raro al hacer click: la función que los convierte en miniatura con botón de play (youtube_lazy_load()) reemplazaba la miniatura por el iframe original en el mismo lugar sin definir un tamaño, y el botón de play usaba una clase CSS sin top/left definidos, quedando flotando lejos de la miniatura.<br />
<br />
- El buscador global solo aparecía en páginas de post individual: en la plantilla del header, el include del formulario de búsqueda estaba envuelto en una condición (&#36;tsPage == 'posts' &amp;&amp; &#36;tsPost.post_id) sin ninguna razón aparente (el formulario no depende de esas variables).<br />
<br />
-  Los botones "Olvidé mi contraseña" / "No me llegó el correo de confirmación" en el login llaman a remind_password()/resend_validation() en el onclick, pero esas funciones JS no existen en ningún archivo, parecen quedar de una función que nunca se implementó.<br />
<br />
4. <span style="font-weight: bold;" class="mycode_b">SEGURIDAD</span><br />
<br />
- Inyección SQL en getMyPosts() (c.portal.php): los IDs de categoría guardados (u_portal.last_posts_cats) se concatenan directo en la query con implode() sin sanitizar ni castear a int. Además, si el array de categorías queda con un string vacío adentro, produce IN () (SQL inválido → error 500).<br />
<br />
5. <span style="font-weight: bold;" class="mycode_b">CHECKBOXES/RADIOS QUE NO REFLEJAN LA SELECCIÓN REAL (bug clásico de jQuery)</span><br />
<br />
Encontramos este mismo patrón repetido en al menos 3 lugares distintos del código: se usa &#36;(elem).attr('checked') (o .attr('disabled', '')) para leer/cambiar el estado de un checkbox/radio/input después de que el usuario interactúa con él. El problema es que .attr() refleja el atributo HTML original (con el que se renderizó la página), no el estado real después de un click, para eso hace falta .prop().<br />
<br />
- Checkboxes de "categorías de interés" en /mi/ (portal.js, save_configs()) no se guardaban nunca, por leer con .attr('checked') en vez de .prop('checked').<br />
<br />
- Al suspender a un miembro de una comunidad, el sistema siempre aplicaba "Cambiar rango" en su lugar: en comunidades.js, member_admin_submit() lee .attr('checked') sobre un selector que matchea los dos radios del formulario (mismo name); jQuery devuelve el atributo del primero que encuentra, que queda marcado desde el HTML y nunca se limpia. Resultado: no importa cuál elija el moderador, siempre se interpreta como "Cambiar rango", la suspensión nunca se ejecuta.<br />
<br />
- El campo de URL para adjuntar un enlace/foto/video en el muro queda bloqueado para siempre si la primera URL ingresada es inválida: se deshabilita con .attr('disabled', 'true') y se intenta re-habilitar con .attr('disabled', ''), que en HTML sigue siendo un atributo "presente" (=deshabilitado). Solo se soluciona refrescando toda la página.<br />
<br />
6. <span style="font-weight: bold;" class="mycode_b">DOBLE-ESCAPADO DE HTML EN LOS ADJUNTOS DEL MURO</span><br />
<br />
- El título de un video de YouTube compartido se guarda con las entidades HTML duplicadas (por ejemplo, un "&amp;" termina guardado como "&amp;" en vez de "&amp;", y una comilla como "'" literal en vez de la comilla real en enlaces compartidos): el título llega desde get_meta_tags() ya con las entidades HTML codificadas una vez (así lo entrega YouTube), y el código lo vuelve a pasar por htmlspecialchars() sin decodificar primero. Encontramos el mismo patrón en foto, enlace y video: ajaxCheck(&#36;return=true) ya devuelve los valores escapados, y streamPost() los vuelve a escapar antes del INSERT, doble pasada de escapado sobre el mismo valor.<br />
<br />
7. <span style="font-weight: bold;" class="mycode_b">VISTA PREVIA DE ADJUNTOS EN EL MURO NO SE MOSTRABA</span><br />
<br />
- Al adjuntar una foto o un enlace en el composer del muro, después de dar clic en "Adjuntar" la tarjeta de previsualización (imagen + título + descripción) nunca aparecía visualmente, aunque el AJAX funcionara bien. Causa: una regla CSS muy genérica en el tema, #attaContent div{display:none}, oculta cualquier &lt;div&gt; hijo del composer, y el HTML de la tarjeta no traía display seteado explícito para ganarle a esa regla.<br />
============================================================================================<br />
<span style="font-weight: bold;" class="mycode_b"><span style="font-size: x-large;" class="mycode_size">paises que no tienen provincia en el formulario de perfil</span></span><br />
<br />
anguila, ciudad del vaticano, eslovenia, filipinas, groenlandia, guam, hong kong, isla bouvet, isla de man, isla navidad, islandia, islas caiman, islas cocos, islas cook, islas feroe, islas georgias del sur y sandwich del sur, islas heard y mcdonald, islas marianas del norte, islas marshall, islas pitcairn, islas salomon, islas turcas y caicos, islas virgenes britanicas, islas virgenes estadounidenses, islas ultramarinas de estados unidos, jersey, libia, liechtenstein, malta, mayotte, moldavia, nauru, niue, norfolk, nueva caledonia, oman, polinesia francesa, republica centroafricana, republica checa, republica democratica del congo, republica dominicana, republica de macedonia, republica del congo, republica arabe saharaui democratica, reunion, ruanda, saint-martin, samoa, samoa americana, san bartolome, seychelles, singapur, siria, somalia, sri lanka, suazilandia, sudan, surinam, svalbard y jan mayen, tayikistan, territorio britanico del oceano indico, territorio australes franceses, territorios palestinos, timor oriental, tokelau, tonga, turkmenistan, tuvalu, uganda, uzbekistan, vanuatu, wallis y futuna, yemen, yibuti y zimbabue.<br />
<span style="font-weight: bold;" class="mycode_b">si. lo revise uno por uno lol</span><br />
<br />
<span style="font-weight: bold;" class="mycode_b">aqui esta un fix rapido que me creo claude del geodata.php:</span><br />
Registrate o inicia tu sesión para ver este contenido<br />
----------------------------------------------------------------------------------------------<br />
<span style="font-weight: bold;" class="mycode_b">9.vulnerabilidad de seguridad real:</span> en el editor de posts (/agregar/), cuando pegás un link solo en una línea, se genera automáticamente una tarjeta de vista previa (link-preview.js). El título, la descripción y el dominio pasaban por un escapeHtml() antes de insertarse en el HTML — pero la imagen (og:image, sacada de un sitio externo cualquiera) y el link se insertaban sin escapar, directo dentro de un atributo src="...".<br />
<br />
Cualquiera podría poner en su propia página un og:image con algo como content='x.jpg" onerror="robar_cookies()"', y si alguien pegaba ese link en un post, ese HTML malicioso quedaba guardado dentro del post — ejecutándose para todos los que lo vieran después (XSS almacenado). fix: agregando el mismo escape a esos dos campos.<br />
<br />
Además revisé:<br />
<br />
Otros lugares con posible inyección SQL (c.actividad.php, c.mensajes.php, c.admin.php, c.sugerencias.php) — todos están bien sanitizados, no encontré más.<br />
El mismo patrón de HTML sin escapar en otros archivos JS — encontré usos similares con datos de TMDB (posters de películas), pero esos vienen de una API/catálogo curado, no de cualquier sitio externo, así que el riesgo es mucho menor y no lo toqué.<br />
========================================================================<br />
<span style="font-weight: bold;" class="mycode_b"><span style="color: #3498db;" class="mycode_color">Actualización — después del post original:</span></span><br />
<br />
<span style="font-weight: bold;" class="mycode_b">10. LLAMADA A MÉTODO INEXISTENTE TRAS UN REFACTOR</span><br />
<br />
Error 500 (fatal) al enviar el formulario de "Olvidé mi contraseña" / "No me llegó el correo de confirmación": en inc/php/ajax/ajax.recover.php (rutas recover-pass / recover-validation) queda una línea residual &#36;tsEmail-&gt;emailHeaders = &#36;tsEmail-&gt;setEmailHeaders();. En algún momento c.emails.php se reescribió para usar SMTP/PHPMailer y el método setEmailHeaders() ya no existe en la clase — la llamada quedó huérfana. Confirmado en el error.log del servidor. Fix: eliminar esa línea (no hace falta, PHPMailer maneja los headers solo).<br />
<br />
<span style="font-weight: bold;" class="mycode_b">11. FEATURE MAL ETIQUETADA / INCOMPLETA [OPCIONAL] </span><br />
<br />
La pestaña "Mis posts" en /mi/ en realidad no muestra los posts que escribió el usuario: muestra "últimos posts de tu interés" (un filtro por categorías guardadas), no posts de autoría propia. El nombre de la pestaña es engañoso — no hay ningún método en el código que filtre por post_user para esta vista. Fix que aplicamos: agregamos un getAuthoredPosts() nuevo (filtra por post_user) como pestaña real "Mis posts", y renombramos la de categorías a "De mi interés".<br />
<br />
<br />
<br />
<span style="font-weight: bold;" class="mycode_b">NOTA:</span> esto es generado con inteligencia artificial que comete errores, pero dirigido por mí. Le digo qué hacer y dónde buscar. Pongo esto aquí con fines de ayudar. Gracias.]]></description>
			<content:encoded><![CDATA[Hola! estoy corriendo Risus Nova v2.1 en un entorno local con PHP 8.2.12 con ayuda de claude code y fuimos encontrando varios bugs? del core. Los reporto acá con la causa y el fix que aplicamos, por si sirve para una próxima actualización. Los divido por categoría.<br />
<br />
1.<span style="font-weight: bold;" class="mycode_b"> INCOMPATIBILIDADES CON PHP 8.x</span><br />
<br />
- Error 500 al guardar el perfil si se deja un checkbox "Me gustaría" sin marcar: en c.cuenta.php, se accede a &#36;_POST['g_'.&#36;i] sin verificar que exista. Los checkboxes no marcados no viajan en el POST, y en PHP 8.2 pasar null a una función que espera string es un TypeError fatal. Fix: &#36;_POST['g_'.&#36;i] ?? ''.<br />
<br />
- Error 500 al guardar "Sitio Web" con una URL válida: se usa la constante FILTER_FLAG_HOST_REQUIRED en filter_var(), eliminada en PHP 8. Fix: sacar ese tercer argumento.<br />
<br />
2. <span style="font-weight: bold;" class="mycode_b">URLs/REDIRECCIONES ROTAS EN INSTALACIONES EN SUBDIRECTORIO</span><br />
<br />
- Redirecciones de login (setLevel(), redirectTo() en c.core.php) arman la URL a mano sin anteponer &#36;this-&gt;settings['url'], así que en cualquier instalación que NO viva en la raíz del dominio (ej. midominio.com/foro/), termina redirigiendo a midominio.com/login/... (sin el subdirectorio) → 404.<br />
<br />
- Botones "Volver al listado" (/admin/news) y "Mover Posts" (/admin/cats) en el panel de admin usan location.href = '/admin/...' hardcodeado en las plantillas, mismo problema.<br />
<br />
- Ícono de RSS de "Últimos posts" en el home también hardcodea /rss/ultimos-post sin el prefijo.<br />
<br />
3. <span style="font-weight: bold;" class="mycode_b">BUGS DE LÓGICA / FUNCIONES INCOMPLETAS</span><br />
<br />
- /admin/creditos muestra la librería GD como N/A aunque esté instalada y funcionando: el bloque elseif(&#36;action=='creditos') de admin.php nunca asigna &#36;smarty-&gt;assign("tsVersion", &#36;tsAdmin-&gt;getVersions()).<br />
<br />
- Selects de país/estado/mes/año vacíos en /cuenta/perfil: el bloque que asigna esos datos en cuenta.php corre con if(empty(&#36;action)), pero la ruta real entra con &#36;action='perfil', así que nunca se ejecuta.<br />
<br />
- Faltan las provincias/estados de ~80 países en geodata.php (confirmado con República Dominicana, Islandia, Singapur, entre otros): el array &#36;estados[...] simplemente no los tiene cargados.<br />
<br />
- Selects "Fumo" y "Tomo alcohol" vacíos (sección "Cómo soy" del perfil): en datos.php solo existe el array combinado fumo_tomo, pero la plantilla busca fumo y alcohol por separado (no existen).<br />
<br />
- "Me gustaría" (checkboxes) no se mostraba en el perfil: typo en la plantilla, pide &#36;tsPData.gustaria/&#36;tsPerfil.p_gustaria en vez de .gustos/.p_gustos (el nombre real usado en toda la base de datos y el resto del código).<br />
<br />
- /retos/ da "No direct access." y luego error 500: tres bugs apilados. Falta la regla en .htaccess (las páginas hermanas como calendario/misiones/premios sí la tienen), el guard chequea una constante que no existe en ningún lado del código (TSCRIPT en vez de TS_HEADER), y después de rutear bien, llama a &#36;tsCore-&gt;setTitle(), un método que no existe en la clase.<br />
<br />
- muro.load_atta() (JS del muro) está sin terminar: recibe la URL de la foto/video adjunto al hacer click, pero nunca la usa, reemplaza el elemento clickeado por una imagen vacía o un string vacío, haciendo "desaparecer" la foto/video en vez de mostrarla en grande.<br />
<br />
- Avatar GIF animado se queda estático en todo el sitio: imagecreatefromgif() + imagejpeg() de GD solo puede leer/escribir UN cuadro, así que cualquier GIF que pase por el recorte/generación de miniaturas del avatar (c.upload.php) pierde la animación.<br />
<br />
- Imagen de fondo de perfil no se aplicaba nunca: typo de tipo MIME en la plantilla, &lt;style type="text/style"&gt; en vez de text/css. Por spec de HTML5 los navegadores ignoran por completo un &lt;style&gt; con type inválido, así que el background-image nunca se veía aunque la URL fuera correcta.<br />
<br />
- Portada de perfil no se mostraba en /mi/: el controlador (portal.php) solo carga &#36;tsPerfil condicionalmente (para el aviso de bienvenida a cuentas nuevas), nunca de forma incondicional para el resto de la página.<br />
<br />
- Al subir una foto de perfil inválida, el mensaje de error mostraba [object Object] en vez del texto real, porque el callback de éxito solo sabía manejar dos formatos de respuesta distintos y no el de error real del servidor.<br />
<br />
- "Subir por URL" para avatar rechazaba links de imagen con ?token=... (típico en CDNs como *****): la validación de extensión de archivo no ignoraba el query string de la URL.<br />
<br />
- Videos de YouTube embebidos en el cuerpo de un post se comportaban raro al hacer click: la función que los convierte en miniatura con botón de play (youtube_lazy_load()) reemplazaba la miniatura por el iframe original en el mismo lugar sin definir un tamaño, y el botón de play usaba una clase CSS sin top/left definidos, quedando flotando lejos de la miniatura.<br />
<br />
- El buscador global solo aparecía en páginas de post individual: en la plantilla del header, el include del formulario de búsqueda estaba envuelto en una condición (&#36;tsPage == 'posts' &amp;&amp; &#36;tsPost.post_id) sin ninguna razón aparente (el formulario no depende de esas variables).<br />
<br />
-  Los botones "Olvidé mi contraseña" / "No me llegó el correo de confirmación" en el login llaman a remind_password()/resend_validation() en el onclick, pero esas funciones JS no existen en ningún archivo, parecen quedar de una función que nunca se implementó.<br />
<br />
4. <span style="font-weight: bold;" class="mycode_b">SEGURIDAD</span><br />
<br />
- Inyección SQL en getMyPosts() (c.portal.php): los IDs de categoría guardados (u_portal.last_posts_cats) se concatenan directo en la query con implode() sin sanitizar ni castear a int. Además, si el array de categorías queda con un string vacío adentro, produce IN () (SQL inválido → error 500).<br />
<br />
5. <span style="font-weight: bold;" class="mycode_b">CHECKBOXES/RADIOS QUE NO REFLEJAN LA SELECCIÓN REAL (bug clásico de jQuery)</span><br />
<br />
Encontramos este mismo patrón repetido en al menos 3 lugares distintos del código: se usa &#36;(elem).attr('checked') (o .attr('disabled', '')) para leer/cambiar el estado de un checkbox/radio/input después de que el usuario interactúa con él. El problema es que .attr() refleja el atributo HTML original (con el que se renderizó la página), no el estado real después de un click, para eso hace falta .prop().<br />
<br />
- Checkboxes de "categorías de interés" en /mi/ (portal.js, save_configs()) no se guardaban nunca, por leer con .attr('checked') en vez de .prop('checked').<br />
<br />
- Al suspender a un miembro de una comunidad, el sistema siempre aplicaba "Cambiar rango" en su lugar: en comunidades.js, member_admin_submit() lee .attr('checked') sobre un selector que matchea los dos radios del formulario (mismo name); jQuery devuelve el atributo del primero que encuentra, que queda marcado desde el HTML y nunca se limpia. Resultado: no importa cuál elija el moderador, siempre se interpreta como "Cambiar rango", la suspensión nunca se ejecuta.<br />
<br />
- El campo de URL para adjuntar un enlace/foto/video en el muro queda bloqueado para siempre si la primera URL ingresada es inválida: se deshabilita con .attr('disabled', 'true') y se intenta re-habilitar con .attr('disabled', ''), que en HTML sigue siendo un atributo "presente" (=deshabilitado). Solo se soluciona refrescando toda la página.<br />
<br />
6. <span style="font-weight: bold;" class="mycode_b">DOBLE-ESCAPADO DE HTML EN LOS ADJUNTOS DEL MURO</span><br />
<br />
- El título de un video de YouTube compartido se guarda con las entidades HTML duplicadas (por ejemplo, un "&amp;" termina guardado como "&amp;" en vez de "&amp;", y una comilla como "'" literal en vez de la comilla real en enlaces compartidos): el título llega desde get_meta_tags() ya con las entidades HTML codificadas una vez (así lo entrega YouTube), y el código lo vuelve a pasar por htmlspecialchars() sin decodificar primero. Encontramos el mismo patrón en foto, enlace y video: ajaxCheck(&#36;return=true) ya devuelve los valores escapados, y streamPost() los vuelve a escapar antes del INSERT, doble pasada de escapado sobre el mismo valor.<br />
<br />
7. <span style="font-weight: bold;" class="mycode_b">VISTA PREVIA DE ADJUNTOS EN EL MURO NO SE MOSTRABA</span><br />
<br />
- Al adjuntar una foto o un enlace en el composer del muro, después de dar clic en "Adjuntar" la tarjeta de previsualización (imagen + título + descripción) nunca aparecía visualmente, aunque el AJAX funcionara bien. Causa: una regla CSS muy genérica en el tema, #attaContent div{display:none}, oculta cualquier &lt;div&gt; hijo del composer, y el HTML de la tarjeta no traía display seteado explícito para ganarle a esa regla.<br />
============================================================================================<br />
<span style="font-weight: bold;" class="mycode_b"><span style="font-size: x-large;" class="mycode_size">paises que no tienen provincia en el formulario de perfil</span></span><br />
<br />
anguila, ciudad del vaticano, eslovenia, filipinas, groenlandia, guam, hong kong, isla bouvet, isla de man, isla navidad, islandia, islas caiman, islas cocos, islas cook, islas feroe, islas georgias del sur y sandwich del sur, islas heard y mcdonald, islas marianas del norte, islas marshall, islas pitcairn, islas salomon, islas turcas y caicos, islas virgenes britanicas, islas virgenes estadounidenses, islas ultramarinas de estados unidos, jersey, libia, liechtenstein, malta, mayotte, moldavia, nauru, niue, norfolk, nueva caledonia, oman, polinesia francesa, republica centroafricana, republica checa, republica democratica del congo, republica dominicana, republica de macedonia, republica del congo, republica arabe saharaui democratica, reunion, ruanda, saint-martin, samoa, samoa americana, san bartolome, seychelles, singapur, siria, somalia, sri lanka, suazilandia, sudan, surinam, svalbard y jan mayen, tayikistan, territorio britanico del oceano indico, territorio australes franceses, territorios palestinos, timor oriental, tokelau, tonga, turkmenistan, tuvalu, uganda, uzbekistan, vanuatu, wallis y futuna, yemen, yibuti y zimbabue.<br />
<span style="font-weight: bold;" class="mycode_b">si. lo revise uno por uno lol</span><br />
<br />
<span style="font-weight: bold;" class="mycode_b">aqui esta un fix rapido que me creo claude del geodata.php:</span><br />
Registrate o inicia tu sesión para ver este contenido<br />
----------------------------------------------------------------------------------------------<br />
<span style="font-weight: bold;" class="mycode_b">9.vulnerabilidad de seguridad real:</span> en el editor de posts (/agregar/), cuando pegás un link solo en una línea, se genera automáticamente una tarjeta de vista previa (link-preview.js). El título, la descripción y el dominio pasaban por un escapeHtml() antes de insertarse en el HTML — pero la imagen (og:image, sacada de un sitio externo cualquiera) y el link se insertaban sin escapar, directo dentro de un atributo src="...".<br />
<br />
Cualquiera podría poner en su propia página un og:image con algo como content='x.jpg" onerror="robar_cookies()"', y si alguien pegaba ese link en un post, ese HTML malicioso quedaba guardado dentro del post — ejecutándose para todos los que lo vieran después (XSS almacenado). fix: agregando el mismo escape a esos dos campos.<br />
<br />
Además revisé:<br />
<br />
Otros lugares con posible inyección SQL (c.actividad.php, c.mensajes.php, c.admin.php, c.sugerencias.php) — todos están bien sanitizados, no encontré más.<br />
El mismo patrón de HTML sin escapar en otros archivos JS — encontré usos similares con datos de TMDB (posters de películas), pero esos vienen de una API/catálogo curado, no de cualquier sitio externo, así que el riesgo es mucho menor y no lo toqué.<br />
========================================================================<br />
<span style="font-weight: bold;" class="mycode_b"><span style="color: #3498db;" class="mycode_color">Actualización — después del post original:</span></span><br />
<br />
<span style="font-weight: bold;" class="mycode_b">10. LLAMADA A MÉTODO INEXISTENTE TRAS UN REFACTOR</span><br />
<br />
Error 500 (fatal) al enviar el formulario de "Olvidé mi contraseña" / "No me llegó el correo de confirmación": en inc/php/ajax/ajax.recover.php (rutas recover-pass / recover-validation) queda una línea residual &#36;tsEmail-&gt;emailHeaders = &#36;tsEmail-&gt;setEmailHeaders();. En algún momento c.emails.php se reescribió para usar SMTP/PHPMailer y el método setEmailHeaders() ya no existe en la clase — la llamada quedó huérfana. Confirmado en el error.log del servidor. Fix: eliminar esa línea (no hace falta, PHPMailer maneja los headers solo).<br />
<br />
<span style="font-weight: bold;" class="mycode_b">11. FEATURE MAL ETIQUETADA / INCOMPLETA [OPCIONAL] </span><br />
<br />
La pestaña "Mis posts" en /mi/ en realidad no muestra los posts que escribió el usuario: muestra "últimos posts de tu interés" (un filtro por categorías guardadas), no posts de autoría propia. El nombre de la pestaña es engañoso — no hay ningún método en el código que filtre por post_user para esta vista. Fix que aplicamos: agregamos un getAuthoredPosts() nuevo (filtra por post_user) como pestaña real "Mis posts", y renombramos la de categorías a "De mi interés".<br />
<br />
<br />
<br />
<span style="font-weight: bold;" class="mycode_b">NOTA:</span> esto es generado con inteligencia artificial que comete errores, pero dirigido por mí. Le digo qué hacer y dónde buscar. Pongo esto aquí con fines de ayudar. Gracias.]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[Vídeos v1.5]]></title>
			<link>https://phpost.es/tema-COMPLEMENTOS-V%C3%ADdeos-v1-5</link>
			<pubDate>Thu, 09 Jul 2026 13:18:03 +0200</pubDate>
			<dc:creator><![CDATA[<a href="https://phpost.es/member.php?action=profile&uid=1">Tronlar</a>]]></dc:creator>
			<guid isPermaLink="false">https://phpost.es/tema-COMPLEMENTOS-V%C3%ADdeos-v1-5</guid>
			<description><![CDATA[<div style="text-align: center;" class="mycode_align"><span style="color: #2980b9;" class="mycode_color"><span style="font-size: x-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Vídeos v1.5</span></span></span><br />
<span style="font-size: large;" class="mycode_size">Actualización del módulo de Vídeos para Risus Nova 2.0 — PHPost</span></div>
<hr class="mycode_hr" />
<br />
<span style="font-weight: bold;" class="mycode_b"><span style="color: #2980b9;" class="mycode_color"><span style="font-size: x-large;" class="mycode_size">Capturas</span></span></span><br />
<div style="text-align: center;" class="mycode_align"><img src="https://i.imgur.com/gJTMPf4.png" loading="lazy"  alt="[Imagen: gJTMPf4.png]" class="mycode_img img-responsive" /></div>
 <br />
<div style="text-align: center;" class="mycode_align"><img src="https://i.imgur.com/ZclVYr0.png" loading="lazy"  alt="[Imagen: ZclVYr0.png]" class="mycode_img img-responsive" /></div>
 <br />
<div style="text-align: center;" class="mycode_align"><img src="https://i.imgur.com/90QpwV8.gif" loading="lazy"  alt="[Imagen: 90QpwV8.gif]" class="mycode_img img-responsive" /></div>
 <br />
<div style="text-align: center;" class="mycode_align"><img src="https://i.imgur.com/4R2mASs.png" loading="lazy"  alt="[Imagen: 4R2mASs.png]" class="mycode_img img-responsive" /></div>
 <br />
<div style="text-align: center;" class="mycode_align"><img src="https://i.imgur.com/ooClT4Q.png" loading="lazy"  alt="[Imagen: ooClT4Q.png]" class="mycode_img img-responsive" /></div>
 <br />
<div style="text-align: center;" class="mycode_align"><img src="https://i.imgur.com/nDTNOSA.png" loading="lazy"  alt="[Imagen: nDTNOSA.png]" class="mycode_img img-responsive" /></div>
 <br />
<div style="text-align: center;" class="mycode_align"><img src="https://i.imgur.com/saRfQjS.png" loading="lazy"  alt="[Imagen: saRfQjS.png]" class="mycode_img img-responsive" /></div>
 <br />
<div style="text-align: center;" class="mycode_align"><img src="https://i.imgur.com/mK8CawO.png" loading="lazy"  alt="[Imagen: mK8CawO.png]" class="mycode_img img-responsive" /></div>
<hr class="mycode_hr" />
<br />
<span style="font-size: large;" class="mycode_size">Sistema completo de vídeos hecho desde cero para Risus Nova 2.0. Soporta YouTube y Vimeo, con comentarios, reportes, panel admin y control de permisos por rango.</span><br />
 <br />
<hr class="mycode_hr" />
<br />
<span style="color: #e74c3c;" class="mycode_color"><span style="font-size: x-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">🆕 Novedades en la v1.5</span></span></span><br />
 <ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Miniaturas reales de Vimeo</span> — hasta ahora los vídeos de Vimeo solo mostraban un icono genérico en vez de portada. Ahora el módulo consulta la API oficial de cada plataforma (YouTube y Vimeo) al publicar el vídeo y guarda la miniatura real, en vez de intentar adivinarla</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Arreglado el mismo problema en la sección "Más vídeos de este usuario" dentro de la vista de un vídeo, que también ignoraba las miniaturas de Vimeo</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Nueva columna <span style="font-weight: bold;" class="mycode_b">vid_thumb</span> en la base de datos para guardar la miniatura de forma persistente</span><br />
</li>
</ul>
<br />
<span style="color: #e74c3c;" class="mycode_color"><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">⚠️ ¿Vienes de la v1.0?</span></span></span><br />
<span style="font-size: large;" class="mycode_size">No hace falta reinstalar desde cero. Solo tienes que:</span><br />
 <br />
<ol type="1" class="mycode_list"><li><span style="font-size: large;" class="mycode_size">Ejecutar esta consulta SQL una vez, en phpMyAdmin:</span><br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>ALTER TABLE `v_videos` ADD `vid_thumb` VARCHAR(255) NOT NULL DEFAULT '' AFTER `vid_embed`;</code></div></div></li>
<li><span style="font-size: large;" class="mycode_size">Sustituir estos 3 archivos por los de esta versión:</span><br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>inc/class/c.videos.php<br />
themes/default/templates/modules/m.video_card.tpl<br />
themes/default/templates/modules/m.video_ver.tpl</code></div></div></li>
<li><span style="font-size: large;" class="mycode_size">Borrar la caché (<span style="font-weight: bold;" class="mycode_b">/cache/</span>)</span><br />
</li>
</ol>
<br />
<span style="font-size: large;" class="mycode_size">Los vídeos que ya tenías publicados se quedarán sin miniatura real hasta que los vuelvas a guardar, o si prefieres, puedes rellenarlas a mano con una consulta UPDATE usando el mismo patrón de YouTube (`img.youtube.com/vi/{id}/hqdefault.jpg`) para los tuyos.</span><br />
 <br />
<hr class="mycode_hr" />
<br />
<span style="color: #2980b9;" class="mycode_color"><span style="font-size: x-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">🎬 Características</span></span></span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size">Soporte para <span style="font-weight: bold;" class="mycode_b">YouTube</span> y <span style="font-weight: bold;" class="mycode_b">Vimeo</span> — pegar la URL y se genera el reproductor automáticamente</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Grid de tarjetas con la miniatura real del vídeo, sin bandas negras</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Filtro por categoría y orden (nuevos / más vistos)</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Comentarios en cada vídeo</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Sistema de reportes — 3 reportes ocultan el vídeo automáticamente</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Panel admin con gestión de vídeos y categorías</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Control de permisos por rango desde <span style="font-weight: bold;" class="mycode_b">Admin → Rangos</span></span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">7 categorías por defecto (configurables desde el admin)</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Instalador automático — crea todas las tablas</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Diseño responsive</span><br />
</li>
</ul>
 <br />
<hr class="mycode_hr" />
<br />
<span style="color: #2980b9;" class="mycode_color"><span style="font-size: x-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">🛠️ Instalación</span></span></span><br />
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Paso 1 — Ejecutar el instalador</span><br />
<br />
Sube la carpeta <span style="font-weight: bold;" class="mycode_b">install/</span> a la raíz y accede a:</span><br />
 <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>Registrate o inicia tu sesión para ver este contenido</code></div></div><br />
<br />
<span style="color: #2980b9;" class="mycode_color"><span style="font-size: large;" class="mycode_size">El instalador crea automáticamente:</span></span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size">Tabla <span style="font-weight: bold;" class="mycode_b">v_videos</span> (ya incluye la columna vid_thumb)</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Tabla <span style="font-weight: bold;" class="mycode_b">v_categorias</span> con 7 categorías por defecto</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Tabla <span style="font-weight: bold;" class="mycode_b">v_comentarios</span></span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Tabla <span style="font-weight: bold;" class="mycode_b">v_denuncias</span></span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Permiso <span style="font-weight: bold;" class="mycode_b">govid</span> añadido a todos los rangos</span><br />
</li>
</ul>
<br />
<br />
<span style="font-size: x-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">⚠️ Elimina la carpeta install/ cuando termine.</span></span><br />
<br />
<br />
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Paso 2 — Subir los archivos</span></span><br />
 <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>inc/class/c.videos.php&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; →&nbsp;&nbsp;inc/class/<br />
inc/php/videos.php&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; →&nbsp;&nbsp;inc/php/<br />
inc/php/ajax/ajax.videos.php&nbsp;&nbsp;&nbsp;&nbsp; →&nbsp;&nbsp;inc/php/ajax/<br />
t.videos.tpl&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; →&nbsp;&nbsp;themes/default/templates/<br />
m.video_card.tpl&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; →&nbsp;&nbsp;themes/default/templates/modules/<br />
m.video_ver.tpl&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;→&nbsp;&nbsp;themes/default/templates/modules/<br />
m.video_nuevo.tpl&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;→&nbsp;&nbsp;themes/default/templates/modules/<br />
m.admin_videos.tpl&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; →&nbsp;&nbsp;themes/default/templates/modules/<br />
videos.css&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; →&nbsp;&nbsp;themes/default/css/</code></div></div><br />
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Paso 3 — En .htaccess</span></span><br />
<br />
<span style="font-size: large;" class="mycode_size">Arriba de <span style="font-weight: bold;" class="mycode_b"># FOTOS</span> agregar:</span><br />
 <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code># VIDEOS<br />
RewriteRule ^videos/&#36; inc/php/videos.php?action= [QSA,L]<br />
RewriteRule ^videos/ver/([0-9]+)/&#36; inc/php/videos.php?action=ver&amp;vid=&#36;1 [QSA,L]<br />
RewriteRule ^videos/nuevo/&#36; inc/php/videos.php?action=nuevo [QSA,L]<br />
RewriteRule ^videos/usuario/([^/]+)/&#36; inc/php/videos.php?action=usuario&amp;nick=&#36;1 [QSA,L]<br />
RewriteRule ^admin/videos&#36; inc/php/admin.php?action=videos [QSA,L]</code></div></div><br />
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Paso 4 — En admin.php</span></span><br />
<br />
<span style="font-size: large;" class="mycode_size">Buscar:</span><br />
 <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>} elseif(&#36;action == 'feed'){</code></div></div><br />
<br />
Agregar arriba:<br />
 <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>} elseif(&#36;action == 'videos'){<br />
&nbsp;&nbsp;&nbsp;&nbsp;require_once TS_CLASS . 'c.videos.php';<br />
&nbsp;&nbsp;&nbsp;&nbsp;&#36;tsV = new tsVideos();<br />
&nbsp;&nbsp;&nbsp;&nbsp;if (!empty(&#36;_GET['addcat']) &amp;&amp; !empty(&#36;_POST['vcat_name'])) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#36;tsV-&gt;adminSaveCategoria();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#36;tsCore-&gt;redirectTo(&#36;tsCore-&gt;settings['url'].'/admin/videos');<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&#36;filtro = (int)(&#36;_GET['status'] ?? -1);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&#36;smarty-&gt;assign('tsAdminVideos', &#36;tsV-&gt;adminGetVideos());<br />
&nbsp;&nbsp;&nbsp;&nbsp;&#36;smarty-&gt;assign('tsVCategorias', &#36;tsV-&gt;getCategorias());<br />
&nbsp;&nbsp;&nbsp;&nbsp;&#36;smarty-&gt;assign('tsVFiltro', &#36;filtro);</code></div></div><br />
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Paso 5 — En t.admin.tpl</span></span><br />
<br />
<span style="font-size: large;" class="mycode_size">Antes del <span style="font-weight: bold;" class="mycode_b">{/if}</span> final añade:</span><br />
 <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>{elseif &#36;tsAction == 'videos'}<br />
&nbsp;&nbsp;&nbsp;&nbsp;{include file='modules/m.admin_videos.tpl'}</code></div></div><br />
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Paso 6 — En m.admin_rangos.tpl</span></span><br />
<br />
<span style="font-size: large;" class="mycode_size">Buscar:</span><br />
 <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>&lt;dl&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;dt&gt;&lt;label for="goaf"&gt;Anti-flood&lt;/label&gt;&lt;br /&gt;&lt;span&gt;Tiempo que deben esperar entre acci&amp;oacute;n.&lt;/span&gt;&lt;/dt&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;dd&gt;&lt;input type="text" id="goaf" name="global-antiflood" value="{&#36;tsRango.permisos.goaf}" style="width:30%"/&gt;&lt;/dd&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/dl&gt;</code></div></div><br />
<br />
<span style="font-size: large;" class="mycode_size">Debajo agregar:</span><br />
 <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>&lt;dl&gt;<br />
&lt;dt&gt;&lt;label for="govid"&gt;Publicar Vídeos&lt;/label&gt;&lt;br /&gt;&lt;span&gt;Podrán publicar vídeos en el sitio.&lt;/span&gt;&lt;/dt&gt;<br />
&lt;dd&gt;&lt;input type="checkbox" id="govid" name="global-publicarvideos" {if &#36;tsRango.permisos.govid == 'on'}checked{/if} /&gt;&lt;/dd&gt;<br />
&lt;/dl&gt;</code></div></div><br />
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Paso 7 — En c.admin.php</span></span><br />
<br />
<span style="font-size: large;" class="mycode_size">Buscar:</span><br />
<br />
<span style="font-size: large;" class="mycode_size">En <span style="font-weight: bold;" class="mycode_b">saveRango()</span> y <span style="font-weight: bold;" class="mycode_b">newRango()</span> busca la línea:</span><br />
 <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>'gopfd' =&gt; &#36;_POST['global-pointsforday']);</code></div></div><br />
<br />
<span style="font-size: large;" class="mycode_size">Reemplazar por:</span><br />
 <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>'gopfd' =&gt; &#36;_POST['global-pointsforday'],<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'govid' =&gt; &#36;_POST['global-publicarvideos'],<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;);</code></div></div><br />
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Paso 8 — En head_menu.tpl</span></span><br />
<br />
<span style="font-size: large;" class="mycode_size">Buscar:</span><br />
 <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>{if &#36;tsConfig.c_fotos_private == '1' &amp;&amp; !&#36;tsUser-&gt;is_member}{else}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;li class="tabbed {if &#36;tsPage == 'fotos'}here{/if}" id="tabbedfotos"&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;a title="Ir a Fotos" onclick="menu('fotos', this.href); return false;" href="{&#36;tsConfig.url}/fotos/"&gt;Fotos &lt;i class="fa-solid fa-caret-down"&gt;&lt;/i&gt;&lt;/a&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/li&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{/if}</code></div></div><br />
<br />
<span style="font-size: large;" class="mycode_size">Debajo agregar:</span><br />
 <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>&lt;li class="tabbed {if &#36;tsPage == 'videos'}here{/if}" id="tabbedvideos"&gt;&lt;a title="Ir a Vídeos" href="{&#36;tsConfig.url}/videos/"&gt;Vídeos &lt;i class="fa-solid fa-film"&gt;&lt;/i&gt;&lt;/a&gt;&lt;/li&gt;</code></div></div><br />
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Paso 9 — Activar el permiso en los rangos</span><br />
<br />
En <span style="font-weight: bold;" class="mycode_b">Admin → Rangos → Editar</span> cada rango y activa <span style="font-weight: bold;" class="mycode_b">Publicar Vídeos</span>.</span><br />
<br />
<br />
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Paso 10 — Borrar la caché</span></span><br />
<br />
<span style="font-size: large;" class="mycode_size">Borra el contenido de la carpeta <span style="font-weight: bold;" class="mycode_b">/cache/</span> del sitio.</span><br />
<hr class="mycode_hr" />
<br />
<span style="font-size: x-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b"><span style="color: #e74c3c;" class="mycode_color">📋 URLs del módulo</span></span></span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size">Portada de vídeos: <span style="font-weight: bold;" class="mycode_b">/videos/</span></span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Ver vídeo: <span style="font-weight: bold;" class="mycode_b">/videos/ver/ID/</span></span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Publicar vídeo: <span style="font-weight: bold;" class="mycode_b">/videos/nuevo/</span></span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Vídeos de usuario: <span style="font-weight: bold;" class="mycode_b">/videos/usuario/NICK/</span></span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Panel admin: <span style="font-weight: bold;" class="mycode_b">/admin/videos</span></span><br />
</li>
</ul>
<hr class="mycode_hr" />
<br />
<span style="font-size: x-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b"><span style="color: #e74c3c;" class="mycode_color">🗑️ Desinstalar</span></span></span><br />
 <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>DROP TABLE IF EXISTS v_videos, v_categorias, v_comentarios, v_denuncias;</code></div></div><br />
<span style="font-size: large;" class="mycode_size">Elimina los archivos y quita los cambios realizados.</span><br />
<hr class="mycode_hr" />
 <br />
<div style="text-align: center;" class="mycode_align"><span style="color: #2980b9;" class="mycode_color"><span style="font-size: x-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Descarga</span></span></span><br />
<br />
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Mediafire</span></span><br />
<a href="http://Registrate%20o%20inicia%20tu%20sesión%20para%20ver%20este%20contenidoídeos+v1.0.rar/file" target="_blank" rel="noopener" class="mycode_url">http://Registrate o inicia tu sesión par...0.rar/file</a><br />
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Google Drive</span></span><br />
<a href="http://Registrate%20o%20inicia%20tu%20sesión%20para%20ver%20este%20contenido" target="_blank" rel="noopener" class="mycode_url">http://Registrate o inicia tu sesión par... contenido</a><br />
<br />
<span style="font-size: large;" class="mycode_size">Hilo original de la v1.0: <a href="http://Registrate%20o%20inicia%20tu%20sesión%20para%20ver%20este%20contenido" target="_blank" rel="noopener" class="mycode_url">http://Registrate o inicia tu sesión par... contenido</a></span><br />
<br />
<span style="font-size: large;" class="mycode_size">¿Tienes dudas o encuentras algún problema? Déjalo en los comentarios.</span><br />
<br />
<br />
<br />
<br />
</div>]]></description>
			<content:encoded><![CDATA[<div style="text-align: center;" class="mycode_align"><span style="color: #2980b9;" class="mycode_color"><span style="font-size: x-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Vídeos v1.5</span></span></span><br />
<span style="font-size: large;" class="mycode_size">Actualización del módulo de Vídeos para Risus Nova 2.0 — PHPost</span></div>
<hr class="mycode_hr" />
<br />
<span style="font-weight: bold;" class="mycode_b"><span style="color: #2980b9;" class="mycode_color"><span style="font-size: x-large;" class="mycode_size">Capturas</span></span></span><br />
<div style="text-align: center;" class="mycode_align"><img src="https://i.imgur.com/gJTMPf4.png" loading="lazy"  alt="[Imagen: gJTMPf4.png]" class="mycode_img img-responsive" /></div>
 <br />
<div style="text-align: center;" class="mycode_align"><img src="https://i.imgur.com/ZclVYr0.png" loading="lazy"  alt="[Imagen: ZclVYr0.png]" class="mycode_img img-responsive" /></div>
 <br />
<div style="text-align: center;" class="mycode_align"><img src="https://i.imgur.com/90QpwV8.gif" loading="lazy"  alt="[Imagen: 90QpwV8.gif]" class="mycode_img img-responsive" /></div>
 <br />
<div style="text-align: center;" class="mycode_align"><img src="https://i.imgur.com/4R2mASs.png" loading="lazy"  alt="[Imagen: 4R2mASs.png]" class="mycode_img img-responsive" /></div>
 <br />
<div style="text-align: center;" class="mycode_align"><img src="https://i.imgur.com/ooClT4Q.png" loading="lazy"  alt="[Imagen: ooClT4Q.png]" class="mycode_img img-responsive" /></div>
 <br />
<div style="text-align: center;" class="mycode_align"><img src="https://i.imgur.com/nDTNOSA.png" loading="lazy"  alt="[Imagen: nDTNOSA.png]" class="mycode_img img-responsive" /></div>
 <br />
<div style="text-align: center;" class="mycode_align"><img src="https://i.imgur.com/saRfQjS.png" loading="lazy"  alt="[Imagen: saRfQjS.png]" class="mycode_img img-responsive" /></div>
 <br />
<div style="text-align: center;" class="mycode_align"><img src="https://i.imgur.com/mK8CawO.png" loading="lazy"  alt="[Imagen: mK8CawO.png]" class="mycode_img img-responsive" /></div>
<hr class="mycode_hr" />
<br />
<span style="font-size: large;" class="mycode_size">Sistema completo de vídeos hecho desde cero para Risus Nova 2.0. Soporta YouTube y Vimeo, con comentarios, reportes, panel admin y control de permisos por rango.</span><br />
 <br />
<hr class="mycode_hr" />
<br />
<span style="color: #e74c3c;" class="mycode_color"><span style="font-size: x-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">🆕 Novedades en la v1.5</span></span></span><br />
 <ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Miniaturas reales de Vimeo</span> — hasta ahora los vídeos de Vimeo solo mostraban un icono genérico en vez de portada. Ahora el módulo consulta la API oficial de cada plataforma (YouTube y Vimeo) al publicar el vídeo y guarda la miniatura real, en vez de intentar adivinarla</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Arreglado el mismo problema en la sección "Más vídeos de este usuario" dentro de la vista de un vídeo, que también ignoraba las miniaturas de Vimeo</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Nueva columna <span style="font-weight: bold;" class="mycode_b">vid_thumb</span> en la base de datos para guardar la miniatura de forma persistente</span><br />
</li>
</ul>
<br />
<span style="color: #e74c3c;" class="mycode_color"><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">⚠️ ¿Vienes de la v1.0?</span></span></span><br />
<span style="font-size: large;" class="mycode_size">No hace falta reinstalar desde cero. Solo tienes que:</span><br />
 <br />
<ol type="1" class="mycode_list"><li><span style="font-size: large;" class="mycode_size">Ejecutar esta consulta SQL una vez, en phpMyAdmin:</span><br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>ALTER TABLE `v_videos` ADD `vid_thumb` VARCHAR(255) NOT NULL DEFAULT '' AFTER `vid_embed`;</code></div></div></li>
<li><span style="font-size: large;" class="mycode_size">Sustituir estos 3 archivos por los de esta versión:</span><br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>inc/class/c.videos.php<br />
themes/default/templates/modules/m.video_card.tpl<br />
themes/default/templates/modules/m.video_ver.tpl</code></div></div></li>
<li><span style="font-size: large;" class="mycode_size">Borrar la caché (<span style="font-weight: bold;" class="mycode_b">/cache/</span>)</span><br />
</li>
</ol>
<br />
<span style="font-size: large;" class="mycode_size">Los vídeos que ya tenías publicados se quedarán sin miniatura real hasta que los vuelvas a guardar, o si prefieres, puedes rellenarlas a mano con una consulta UPDATE usando el mismo patrón de YouTube (`img.youtube.com/vi/{id}/hqdefault.jpg`) para los tuyos.</span><br />
 <br />
<hr class="mycode_hr" />
<br />
<span style="color: #2980b9;" class="mycode_color"><span style="font-size: x-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">🎬 Características</span></span></span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size">Soporte para <span style="font-weight: bold;" class="mycode_b">YouTube</span> y <span style="font-weight: bold;" class="mycode_b">Vimeo</span> — pegar la URL y se genera el reproductor automáticamente</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Grid de tarjetas con la miniatura real del vídeo, sin bandas negras</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Filtro por categoría y orden (nuevos / más vistos)</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Comentarios en cada vídeo</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Sistema de reportes — 3 reportes ocultan el vídeo automáticamente</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Panel admin con gestión de vídeos y categorías</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Control de permisos por rango desde <span style="font-weight: bold;" class="mycode_b">Admin → Rangos</span></span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">7 categorías por defecto (configurables desde el admin)</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Instalador automático — crea todas las tablas</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Diseño responsive</span><br />
</li>
</ul>
 <br />
<hr class="mycode_hr" />
<br />
<span style="color: #2980b9;" class="mycode_color"><span style="font-size: x-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">🛠️ Instalación</span></span></span><br />
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Paso 1 — Ejecutar el instalador</span><br />
<br />
Sube la carpeta <span style="font-weight: bold;" class="mycode_b">install/</span> a la raíz y accede a:</span><br />
 <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>Registrate o inicia tu sesión para ver este contenido</code></div></div><br />
<br />
<span style="color: #2980b9;" class="mycode_color"><span style="font-size: large;" class="mycode_size">El instalador crea automáticamente:</span></span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size">Tabla <span style="font-weight: bold;" class="mycode_b">v_videos</span> (ya incluye la columna vid_thumb)</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Tabla <span style="font-weight: bold;" class="mycode_b">v_categorias</span> con 7 categorías por defecto</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Tabla <span style="font-weight: bold;" class="mycode_b">v_comentarios</span></span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Tabla <span style="font-weight: bold;" class="mycode_b">v_denuncias</span></span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Permiso <span style="font-weight: bold;" class="mycode_b">govid</span> añadido a todos los rangos</span><br />
</li>
</ul>
<br />
<br />
<span style="font-size: x-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">⚠️ Elimina la carpeta install/ cuando termine.</span></span><br />
<br />
<br />
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Paso 2 — Subir los archivos</span></span><br />
 <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>inc/class/c.videos.php&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; →&nbsp;&nbsp;inc/class/<br />
inc/php/videos.php&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; →&nbsp;&nbsp;inc/php/<br />
inc/php/ajax/ajax.videos.php&nbsp;&nbsp;&nbsp;&nbsp; →&nbsp;&nbsp;inc/php/ajax/<br />
t.videos.tpl&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; →&nbsp;&nbsp;themes/default/templates/<br />
m.video_card.tpl&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; →&nbsp;&nbsp;themes/default/templates/modules/<br />
m.video_ver.tpl&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;→&nbsp;&nbsp;themes/default/templates/modules/<br />
m.video_nuevo.tpl&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;→&nbsp;&nbsp;themes/default/templates/modules/<br />
m.admin_videos.tpl&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; →&nbsp;&nbsp;themes/default/templates/modules/<br />
videos.css&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; →&nbsp;&nbsp;themes/default/css/</code></div></div><br />
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Paso 3 — En .htaccess</span></span><br />
<br />
<span style="font-size: large;" class="mycode_size">Arriba de <span style="font-weight: bold;" class="mycode_b"># FOTOS</span> agregar:</span><br />
 <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code># VIDEOS<br />
RewriteRule ^videos/&#36; inc/php/videos.php?action= [QSA,L]<br />
RewriteRule ^videos/ver/([0-9]+)/&#36; inc/php/videos.php?action=ver&amp;vid=&#36;1 [QSA,L]<br />
RewriteRule ^videos/nuevo/&#36; inc/php/videos.php?action=nuevo [QSA,L]<br />
RewriteRule ^videos/usuario/([^/]+)/&#36; inc/php/videos.php?action=usuario&amp;nick=&#36;1 [QSA,L]<br />
RewriteRule ^admin/videos&#36; inc/php/admin.php?action=videos [QSA,L]</code></div></div><br />
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Paso 4 — En admin.php</span></span><br />
<br />
<span style="font-size: large;" class="mycode_size">Buscar:</span><br />
 <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>} elseif(&#36;action == 'feed'){</code></div></div><br />
<br />
Agregar arriba:<br />
 <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>} elseif(&#36;action == 'videos'){<br />
&nbsp;&nbsp;&nbsp;&nbsp;require_once TS_CLASS . 'c.videos.php';<br />
&nbsp;&nbsp;&nbsp;&nbsp;&#36;tsV = new tsVideos();<br />
&nbsp;&nbsp;&nbsp;&nbsp;if (!empty(&#36;_GET['addcat']) &amp;&amp; !empty(&#36;_POST['vcat_name'])) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#36;tsV-&gt;adminSaveCategoria();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#36;tsCore-&gt;redirectTo(&#36;tsCore-&gt;settings['url'].'/admin/videos');<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&#36;filtro = (int)(&#36;_GET['status'] ?? -1);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&#36;smarty-&gt;assign('tsAdminVideos', &#36;tsV-&gt;adminGetVideos());<br />
&nbsp;&nbsp;&nbsp;&nbsp;&#36;smarty-&gt;assign('tsVCategorias', &#36;tsV-&gt;getCategorias());<br />
&nbsp;&nbsp;&nbsp;&nbsp;&#36;smarty-&gt;assign('tsVFiltro', &#36;filtro);</code></div></div><br />
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Paso 5 — En t.admin.tpl</span></span><br />
<br />
<span style="font-size: large;" class="mycode_size">Antes del <span style="font-weight: bold;" class="mycode_b">{/if}</span> final añade:</span><br />
 <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>{elseif &#36;tsAction == 'videos'}<br />
&nbsp;&nbsp;&nbsp;&nbsp;{include file='modules/m.admin_videos.tpl'}</code></div></div><br />
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Paso 6 — En m.admin_rangos.tpl</span></span><br />
<br />
<span style="font-size: large;" class="mycode_size">Buscar:</span><br />
 <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>&lt;dl&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;dt&gt;&lt;label for="goaf"&gt;Anti-flood&lt;/label&gt;&lt;br /&gt;&lt;span&gt;Tiempo que deben esperar entre acci&amp;oacute;n.&lt;/span&gt;&lt;/dt&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;dd&gt;&lt;input type="text" id="goaf" name="global-antiflood" value="{&#36;tsRango.permisos.goaf}" style="width:30%"/&gt;&lt;/dd&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/dl&gt;</code></div></div><br />
<br />
<span style="font-size: large;" class="mycode_size">Debajo agregar:</span><br />
 <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>&lt;dl&gt;<br />
&lt;dt&gt;&lt;label for="govid"&gt;Publicar Vídeos&lt;/label&gt;&lt;br /&gt;&lt;span&gt;Podrán publicar vídeos en el sitio.&lt;/span&gt;&lt;/dt&gt;<br />
&lt;dd&gt;&lt;input type="checkbox" id="govid" name="global-publicarvideos" {if &#36;tsRango.permisos.govid == 'on'}checked{/if} /&gt;&lt;/dd&gt;<br />
&lt;/dl&gt;</code></div></div><br />
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Paso 7 — En c.admin.php</span></span><br />
<br />
<span style="font-size: large;" class="mycode_size">Buscar:</span><br />
<br />
<span style="font-size: large;" class="mycode_size">En <span style="font-weight: bold;" class="mycode_b">saveRango()</span> y <span style="font-weight: bold;" class="mycode_b">newRango()</span> busca la línea:</span><br />
 <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>'gopfd' =&gt; &#36;_POST['global-pointsforday']);</code></div></div><br />
<br />
<span style="font-size: large;" class="mycode_size">Reemplazar por:</span><br />
 <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>'gopfd' =&gt; &#36;_POST['global-pointsforday'],<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'govid' =&gt; &#36;_POST['global-publicarvideos'],<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;);</code></div></div><br />
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Paso 8 — En head_menu.tpl</span></span><br />
<br />
<span style="font-size: large;" class="mycode_size">Buscar:</span><br />
 <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>{if &#36;tsConfig.c_fotos_private == '1' &amp;&amp; !&#36;tsUser-&gt;is_member}{else}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;li class="tabbed {if &#36;tsPage == 'fotos'}here{/if}" id="tabbedfotos"&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;a title="Ir a Fotos" onclick="menu('fotos', this.href); return false;" href="{&#36;tsConfig.url}/fotos/"&gt;Fotos &lt;i class="fa-solid fa-caret-down"&gt;&lt;/i&gt;&lt;/a&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/li&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{/if}</code></div></div><br />
<br />
<span style="font-size: large;" class="mycode_size">Debajo agregar:</span><br />
 <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>&lt;li class="tabbed {if &#36;tsPage == 'videos'}here{/if}" id="tabbedvideos"&gt;&lt;a title="Ir a Vídeos" href="{&#36;tsConfig.url}/videos/"&gt;Vídeos &lt;i class="fa-solid fa-film"&gt;&lt;/i&gt;&lt;/a&gt;&lt;/li&gt;</code></div></div><br />
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Paso 9 — Activar el permiso en los rangos</span><br />
<br />
En <span style="font-weight: bold;" class="mycode_b">Admin → Rangos → Editar</span> cada rango y activa <span style="font-weight: bold;" class="mycode_b">Publicar Vídeos</span>.</span><br />
<br />
<br />
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Paso 10 — Borrar la caché</span></span><br />
<br />
<span style="font-size: large;" class="mycode_size">Borra el contenido de la carpeta <span style="font-weight: bold;" class="mycode_b">/cache/</span> del sitio.</span><br />
<hr class="mycode_hr" />
<br />
<span style="font-size: x-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b"><span style="color: #e74c3c;" class="mycode_color">📋 URLs del módulo</span></span></span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size">Portada de vídeos: <span style="font-weight: bold;" class="mycode_b">/videos/</span></span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Ver vídeo: <span style="font-weight: bold;" class="mycode_b">/videos/ver/ID/</span></span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Publicar vídeo: <span style="font-weight: bold;" class="mycode_b">/videos/nuevo/</span></span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Vídeos de usuario: <span style="font-weight: bold;" class="mycode_b">/videos/usuario/NICK/</span></span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Panel admin: <span style="font-weight: bold;" class="mycode_b">/admin/videos</span></span><br />
</li>
</ul>
<hr class="mycode_hr" />
<br />
<span style="font-size: x-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b"><span style="color: #e74c3c;" class="mycode_color">🗑️ Desinstalar</span></span></span><br />
 <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>DROP TABLE IF EXISTS v_videos, v_categorias, v_comentarios, v_denuncias;</code></div></div><br />
<span style="font-size: large;" class="mycode_size">Elimina los archivos y quita los cambios realizados.</span><br />
<hr class="mycode_hr" />
 <br />
<div style="text-align: center;" class="mycode_align"><span style="color: #2980b9;" class="mycode_color"><span style="font-size: x-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Descarga</span></span></span><br />
<br />
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Mediafire</span></span><br />
<a href="http://Registrate%20o%20inicia%20tu%20sesión%20para%20ver%20este%20contenidoídeos+v1.0.rar/file" target="_blank" rel="noopener" class="mycode_url">http://Registrate o inicia tu sesión par...0.rar/file</a><br />
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Google Drive</span></span><br />
<a href="http://Registrate%20o%20inicia%20tu%20sesión%20para%20ver%20este%20contenido" target="_blank" rel="noopener" class="mycode_url">http://Registrate o inicia tu sesión par... contenido</a><br />
<br />
<span style="font-size: large;" class="mycode_size">Hilo original de la v1.0: <a href="http://Registrate%20o%20inicia%20tu%20sesión%20para%20ver%20este%20contenido" target="_blank" rel="noopener" class="mycode_url">http://Registrate o inicia tu sesión par... contenido</a></span><br />
<br />
<span style="font-size: large;" class="mycode_size">¿Tienes dudas o encuentras algún problema? Déjalo en los comentarios.</span><br />
<br />
<br />
<br />
<br />
</div>]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[Por qué tus correos llegan a spam: SPF, DKIM y DMARC]]></title>
			<link>https://phpost.es/tema-Tutorial-Por-qu%C3%A9-tus-correos-llegan-a-spam-SPF-DKIM-y-DMARC</link>
			<pubDate>Mon, 06 Jul 2026 22:55:19 +0200</pubDate>
			<dc:creator><![CDATA[<a href="https://phpost.es/member.php?action=profile&uid=1">Tronlar</a>]]></dc:creator>
			<guid isPermaLink="false">https://phpost.es/tema-Tutorial-Por-qu%C3%A9-tus-correos-llegan-a-spam-SPF-DKIM-y-DMARC</guid>
			<description><![CDATA[<span style="font-size: x-large;" class="mycode_size"><span style="color: #2980b9;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">Por qué tus correos llegan a spam: SPF, DKIM y DMARC</span></span></span><br />
<br />
<span style="font-size: large;" class="mycode_size">Si los correos de tu foro (activación de cuenta, recuperación de contraseña, notificaciones) acaban en spam o directamente no llegan, casi siempre es por uno de estos tres sistemas mal configurado. Esta guía te explica qué son, sin dar por hecho que sabes nada de antemano.</span><br />
<br />
<span style="font-style: italic;" class="mycode_i"><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Nota:</span> esto no depende de qué software uses (MyBB, Risus Nova, WordPress...) — se configura a nivel de dominio en el DNS, así que aplica igual si instalas Risus Nova en tu propio dominio y envía correos de registro/notificaciones desde ahí.</span></span><br />
 <br />
<hr class="mycode_hr" />
<br />
<span style="font-size: x-large;" class="mycode_size"><span style="color: #2980b9;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">Resumen rápido</span></span></span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">SPF</span> → autoriza qué servidores pueden enviar correo en tu nombre.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">DKIM</span> → firma digitalmente los mensajes para confirmar que son auténticos.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">DMARC</span> → define qué hacer si SPF o DKIM fallan.</span><br />
</li>
</ul>
 <br />
<hr class="mycode_hr" />
<br />
<span style="font-size: large;" class="mycode_size"><span style="color: #2980b9;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">Comprobación rápida</span></span></span><br />
<br />
<span style="font-size: large;" class="mycode_size">Antes de leer toda la teoría, comprueba tu estado actual gratis en <span style="font-weight: bold;" class="mycode_b">Mail-Tester</span> (mail-tester.com): te da una dirección de correo temporal, le envías un email de prueba desde tu web, y te da una puntuación sobre 10 explicando exactamente qué falla.</span><br />
 <br />
<hr class="mycode_hr" />
<br />
<span style="font-size: large;" class="mycode_size"><span style="color: #2980b9;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">¿Por qué existen estos tres sistemas?</span></span></span><br />
<br />
<span style="font-size: large;" class="mycode_size">Cuando el correo electrónico se inventó, no había ninguna forma de comprobar que un email "de Fulano" venía realmente de Fulano — cualquiera podía escribir el remitente que quisiera. Esto se aprovechó masivamente para phishing y spam suplantando marcas conocidas. SPF, DKIM y DMARC se crearon, cada uno en su momento, para tapar ese agujero desde ángulos distintos.</span><br />
 <br />
<hr class="mycode_hr" />
<br />
<span style="font-size: large;" class="mycode_size"><span style="color: #2980b9;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">SPF (Sender Policy Framework)</span></span></span><br />
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Qué hace:</span> es una lista pública de "estos servidores tienen permiso para enviar correos en nombre de mi dominio". Se publica como un registro de texto (TXT) en el DNS de tu dominio.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">Cómo se ve:</span></span><br />
 <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>v=spf1 include:_spf.google.com ~all</code></div></div><br />
<span style="font-size: large;" class="mycode_size">Esto dice: "los servidores de Google Workspace pueden enviar en mi nombre; cualquier otro, trátalo con sospecha (`~all`)".<br />
<br />
<span style="font-weight: bold;" class="mycode_b">Su limitación:</span> SPF solo comprueba el servidor de origen, no si el contenido del mensaje se manipuló por el camino, y deja de funcionar bien si el correo se reenvía a través de otro servidor intermedio.</span><br />
 <br />
<hr class="mycode_hr" />
<br />
<span style="font-size: large;" class="mycode_size"><span style="color: #2980b9;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">DKIM (DomainKeys Identified Mail)</span></span></span><br />
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Qué hace:</span> añade una firma digital criptográfica a cada correo saliente, usando una clave privada que solo tú tienes. El servidor que recibe el correo comprueba esa firma contra una clave pública publicada en tu DNS — si coincide, confirma que el mensaje es auténtico y no se alteró en el camino.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">Cómo se ve:</span> se publica también como registro TXT, con un nombre parecido a:</span><br />
 <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>selector1._domainkey.tudominio.com</code></div></div><br />
<span style="font-size: large;" class="mycode_size">conteniendo una clave larga y cifrada, no legible a simple vista.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">Su ventaja frente a SPF:</span> sí sobrevive al reenvío de correos, porque la firma va pegada al propio mensaje, no depende del servidor que lo entrega en cada salto.</span><br />
 <br />
<hr class="mycode_hr" />
<br />
<span style="font-size: large;" class="mycode_size"><span style="color: #2980b9;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">DMARC (Domain-based Message Authentication, Reporting &amp; Conformance)</span></span></span><br />
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Qué hace:</span> es la "política" que une a los otros dos. Le dice a quien recibe el correo: "si este mensaje falla SPF o DKIM, haz esto" — y te puede mandar informes de quién está intentando enviar correos en tu nombre (útil para detectar suplantación).<br />
<br />
<span style="font-weight: bold;" class="mycode_b">Cómo se ve:</span></span><br />
 <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>v=DMARC1; p=quarantine; rua=mailto:reportes@tudominio.com</code></div></div><br />
<span style="font-size: large;" class="mycode_size">Esto dice: "si falla la comprobación, ponlo en cuarentena (spam), y mándame un informe a esta dirección".<br />
<br />
<span style="font-weight: bold;" class="mycode_b">Los tres niveles de política (`p=`):</span></span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">none</span> — no hagas nada especial, solo mándame informes. Recomendado para empezar, sin arriesgarte a bloquear correos legítimos por error.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">quarantine</span> — manda los correos sospechosos a spam.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">reject</span> — rechaza directamente los correos que fallen. El más estricto, solo recomendable cuando ya confirmaste que SPF/DKIM están bien configurados y no bloquea nada tuyo por error.</span><br />
</li>
</ul>
 <br />
<hr class="mycode_hr" />
<br />
<span style="font-size: large;" class="mycode_size"><span style="color: #2980b9;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">¿Cómo se relacionan los tres entre sí?</span></span></span><br />
 <ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">SPF</span> verifica el servidor de origen.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">DKIM</span> verifica que el contenido es auténtico y no se manipuló.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">DMARC</span> decide qué hacer si alguno de los dos falla, y te informa de los intentos de suplantación.</span><br />
</li>
</ul>
<br />
<span style="font-size: large;" class="mycode_size">Los tres cumplen funciones distintas, pero hoy en día se consideran complementarios — de hecho, DMARC depende técnicamente de que SPF o DKIM estén configurados para poder funcionar. Tener solo uno de los tres deja huecos que los otros dos cubrirían.</span><br />
 <br />
<hr class="mycode_hr" />
<br />
<span style="font-size: large;" class="mycode_size"><span style="color: #2980b9;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">Cómo comprobar si ya los tienes configurados</span></span></span><br />
 <br />
<ol type="1" class="mycode_list"><li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">MXToolbox</span> (mxtoolbox.com) — busca "SPF Record Lookup" y "DMARC Lookup", pega tu dominio.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">IntoDNS</span> (intodns.com) — análisis completo de tu DNS, incluyendo estos tres si están presentes.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Mail-Tester</span> (mail-tester.com) — la prueba más completa, porque envía un correo real y evalúa los tres a la vez con la configuración real de tu servidor.</span><br />
</li>
</ol>
 <br />
<hr class="mycode_hr" />
<br />
<span style="font-size: large;" class="mycode_size"><span style="color: #2980b9;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">Cómo configurarlos si te faltan</span></span></span><br />
<br />
<span style="font-size: large;" class="mycode_size">Los tres se configuran igual: añadiendo un registro TXT en el DNS de tu dominio (en cPanel: Dominios → Zone Editor / Editor de Zonas DNS).</span><br />
 <br />
<ol type="1" class="mycode_list"><li><span style="font-size: large;" class="mycode_size">Pregúntale a tu proveedor de email (Gmail/Google Workspace, tu hosting, etc.) qué valor exacto de SPF necesitas — cada proveedor de correo tiene el suyo propio.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Para DKIM, normalmente tu propio panel de correo (cPanel suele traerlo bajo "Email Deliverability" / "Autenticación de correo") genera automáticamente la clave y te da el registro exacto para pegar.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Para DMARC, empieza siempre con `p=none` durante unas semanas, revisa los informes que te lleguen, y solo entonces sube a `quarantine` o `reject`.</span><br />
</li>
</ol>
 <br />
<hr class="mycode_hr" />
<br />
<span style="font-size: large;" class="mycode_size"><span style="color: #2980b9;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">¿Cómo saber si Gmail confía en tus correos?</span></span></span><br />
<br />
<span style="font-size: large;" class="mycode_size">La forma más sencilla: envía un correo de prueba a una cuenta de Gmail y abre el mensaje → menú de tres puntos → **"Mostrar original"**.<br />
<br />
Ahí verás algo parecido a:</span><br />
 <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>SPF: PASS<br />
DKIM: PASS<br />
DMARC: PASS</code></div></div><br />
<span style="font-size: large;" class="mycode_size">Si alguno aparece como **<span style="font-weight: bold;" class="mycode_b">FAIL</span>**, tienes una pista clara de dónde está el problema — revisa esa sección concreta de esta guía.</span><br />
 <br />
<hr class="mycode_hr" />
<br />
<span style="font-size: x-large;" class="mycode_size"><span style="color: #c0392b;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">Error común: tener varios registros SPF</span></span></span><br />
<br />
<span style="font-size: large;" class="mycode_size">Muchos administradores añaden un SPF nuevo (por ejemplo, al configurar un nuevo proveedor de correo) sin eliminar el anterior. Esto rompe la validación por completo.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">Incorrecto (dos registros SPF separados):</span></span><br />
 <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>v=spf1 include:_spf.google.com ~all<br />
v=spf1 include:otroservicio.com ~all</code></div></div><br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Correcto (todo en un único registro):</span></span><br />
 <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>v=spf1 include:_spf.google.com include:otroservicio.com ~all</code></div></div><br />
<span style="font-size: large;" class="mycode_size">Solo debe existir **un único registro SPF por dominio** — si necesitas autorizar a varios proveedores de correo, se combinan todos dentro del mismo registro con varios `include:`, nunca en líneas separadas.</span><br />
 <br />
<hr class="mycode_hr" />
<br />
<span style="font-size: x-large;" class="mycode_size"><span style="color: #2980b9;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">Preguntas frecuentes</span></span></span><br />
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">¿Necesito los tres, o con uno solo basta?</span><br />
Cada proveedor de correo grande (Gmail, Outlook) valora positivamente tener los tres. Tener solo SPF ya ayuda, pero DKIM y DMARC cierran huecos que SPF no cubre por sí solo.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">¿Puedo romper algo si los configuro mal?</span><br />
Sí — un SPF mal escrito, o un DMARC en `reject` sin haber comprobado antes, puede hacer que tus propios correos legítimos empiecen a rebotar. Por eso se recomienda empezar siempre con la política más suave (`p=none` en DMARC) y subir de nivel solo tras confirmar que todo funciona.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">¿Esto evita que me suplanten por completo?</span><br />
Reduce mucho el riesgo, pero no es 100% infalible — depende también de que el servidor receptor respete tu política DMARC (la mayoría de proveedores grandes sí lo hacen).<br />
<br />
<span style="font-weight: bold;" class="mycode_b">¿Por qué mis correos de MyBB llegan a spam aunque el hosting diga que todo está bien?</span><br />
Es la causa más común de este problema: muchos hostings compartidos no configuran DKIM por defecto, o usan una IP compartida con mala reputación por otros clientes del mismo servidor. Comprobarlo con Mail-Tester te lo confirma de un vistazo.</span><br />
 <br />
<hr class="mycode_hr" />
<br />
<span style="font-size: large;" class="mycode_size"><span style="color: #2980b9;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">¿Y si SPF, DKIM y DMARC están bien pero sigo en spam?</span></span></span><br />
<br />
<span style="font-size: large;" class="mycode_size">Estos tres sistemas ayudan mucho, pero no son el único factor. Los grandes proveedores (Gmail, Outlook, Yahoo) también tienen en cuenta:</span><br />
 <ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size">La reputación de la IP que envía el correo (si esa misma IP la comparten otros clientes de tu hosting que hayan hecho spam antes, te afecta a ti también).</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">La antigüedad del dominio (un dominio recién creado empieza con menos confianza por defecto).</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Las quejas de spam recibidas contra tu dirección o dominio.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">El contenido del propio mensaje (palabras típicas de spam, exceso de enlaces, etc.).</span><br />
</li>
</ul>
<br />
<span style="font-size: large;" class="mycode_size">Por eso puede ocurrir que SPF, DKIM y DMARC estén perfectamente configurados y aun así algunos correos sigan llegando a spam — en ese caso, el problema ya no es de autenticación, sino de reputación general, que se construye con el tiempo enviando correos legítimos de forma constante.</span><br />
 <br />
<hr class="mycode_hr" />
<br />
<span style="font-size: x-large;" class="mycode_size"><span style="color: #27ae60;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">Conclusión</span></span></span><br />
<br />
<span style="font-size: large;" class="mycode_size">Estos tres sistemas no son solo "cosa de empresas grandes" — cualquier web que envíe correos (como un foro con activación de cuenta) se beneficia de tenerlos bien configurados. La forma más rápida de saber dónde estás: una prueba en Mail-Tester te dice en segundos qué de los tres te falta y qué corregir.</span>]]></description>
			<content:encoded><![CDATA[<span style="font-size: x-large;" class="mycode_size"><span style="color: #2980b9;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">Por qué tus correos llegan a spam: SPF, DKIM y DMARC</span></span></span><br />
<br />
<span style="font-size: large;" class="mycode_size">Si los correos de tu foro (activación de cuenta, recuperación de contraseña, notificaciones) acaban en spam o directamente no llegan, casi siempre es por uno de estos tres sistemas mal configurado. Esta guía te explica qué son, sin dar por hecho que sabes nada de antemano.</span><br />
<br />
<span style="font-style: italic;" class="mycode_i"><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Nota:</span> esto no depende de qué software uses (MyBB, Risus Nova, WordPress...) — se configura a nivel de dominio en el DNS, así que aplica igual si instalas Risus Nova en tu propio dominio y envía correos de registro/notificaciones desde ahí.</span></span><br />
 <br />
<hr class="mycode_hr" />
<br />
<span style="font-size: x-large;" class="mycode_size"><span style="color: #2980b9;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">Resumen rápido</span></span></span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">SPF</span> → autoriza qué servidores pueden enviar correo en tu nombre.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">DKIM</span> → firma digitalmente los mensajes para confirmar que son auténticos.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">DMARC</span> → define qué hacer si SPF o DKIM fallan.</span><br />
</li>
</ul>
 <br />
<hr class="mycode_hr" />
<br />
<span style="font-size: large;" class="mycode_size"><span style="color: #2980b9;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">Comprobación rápida</span></span></span><br />
<br />
<span style="font-size: large;" class="mycode_size">Antes de leer toda la teoría, comprueba tu estado actual gratis en <span style="font-weight: bold;" class="mycode_b">Mail-Tester</span> (mail-tester.com): te da una dirección de correo temporal, le envías un email de prueba desde tu web, y te da una puntuación sobre 10 explicando exactamente qué falla.</span><br />
 <br />
<hr class="mycode_hr" />
<br />
<span style="font-size: large;" class="mycode_size"><span style="color: #2980b9;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">¿Por qué existen estos tres sistemas?</span></span></span><br />
<br />
<span style="font-size: large;" class="mycode_size">Cuando el correo electrónico se inventó, no había ninguna forma de comprobar que un email "de Fulano" venía realmente de Fulano — cualquiera podía escribir el remitente que quisiera. Esto se aprovechó masivamente para phishing y spam suplantando marcas conocidas. SPF, DKIM y DMARC se crearon, cada uno en su momento, para tapar ese agujero desde ángulos distintos.</span><br />
 <br />
<hr class="mycode_hr" />
<br />
<span style="font-size: large;" class="mycode_size"><span style="color: #2980b9;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">SPF (Sender Policy Framework)</span></span></span><br />
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Qué hace:</span> es una lista pública de "estos servidores tienen permiso para enviar correos en nombre de mi dominio". Se publica como un registro de texto (TXT) en el DNS de tu dominio.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">Cómo se ve:</span></span><br />
 <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>v=spf1 include:_spf.google.com ~all</code></div></div><br />
<span style="font-size: large;" class="mycode_size">Esto dice: "los servidores de Google Workspace pueden enviar en mi nombre; cualquier otro, trátalo con sospecha (`~all`)".<br />
<br />
<span style="font-weight: bold;" class="mycode_b">Su limitación:</span> SPF solo comprueba el servidor de origen, no si el contenido del mensaje se manipuló por el camino, y deja de funcionar bien si el correo se reenvía a través de otro servidor intermedio.</span><br />
 <br />
<hr class="mycode_hr" />
<br />
<span style="font-size: large;" class="mycode_size"><span style="color: #2980b9;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">DKIM (DomainKeys Identified Mail)</span></span></span><br />
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Qué hace:</span> añade una firma digital criptográfica a cada correo saliente, usando una clave privada que solo tú tienes. El servidor que recibe el correo comprueba esa firma contra una clave pública publicada en tu DNS — si coincide, confirma que el mensaje es auténtico y no se alteró en el camino.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">Cómo se ve:</span> se publica también como registro TXT, con un nombre parecido a:</span><br />
 <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>selector1._domainkey.tudominio.com</code></div></div><br />
<span style="font-size: large;" class="mycode_size">conteniendo una clave larga y cifrada, no legible a simple vista.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">Su ventaja frente a SPF:</span> sí sobrevive al reenvío de correos, porque la firma va pegada al propio mensaje, no depende del servidor que lo entrega en cada salto.</span><br />
 <br />
<hr class="mycode_hr" />
<br />
<span style="font-size: large;" class="mycode_size"><span style="color: #2980b9;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">DMARC (Domain-based Message Authentication, Reporting &amp; Conformance)</span></span></span><br />
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Qué hace:</span> es la "política" que une a los otros dos. Le dice a quien recibe el correo: "si este mensaje falla SPF o DKIM, haz esto" — y te puede mandar informes de quién está intentando enviar correos en tu nombre (útil para detectar suplantación).<br />
<br />
<span style="font-weight: bold;" class="mycode_b">Cómo se ve:</span></span><br />
 <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>v=DMARC1; p=quarantine; rua=mailto:reportes@tudominio.com</code></div></div><br />
<span style="font-size: large;" class="mycode_size">Esto dice: "si falla la comprobación, ponlo en cuarentena (spam), y mándame un informe a esta dirección".<br />
<br />
<span style="font-weight: bold;" class="mycode_b">Los tres niveles de política (`p=`):</span></span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">none</span> — no hagas nada especial, solo mándame informes. Recomendado para empezar, sin arriesgarte a bloquear correos legítimos por error.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">quarantine</span> — manda los correos sospechosos a spam.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">reject</span> — rechaza directamente los correos que fallen. El más estricto, solo recomendable cuando ya confirmaste que SPF/DKIM están bien configurados y no bloquea nada tuyo por error.</span><br />
</li>
</ul>
 <br />
<hr class="mycode_hr" />
<br />
<span style="font-size: large;" class="mycode_size"><span style="color: #2980b9;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">¿Cómo se relacionan los tres entre sí?</span></span></span><br />
 <ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">SPF</span> verifica el servidor de origen.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">DKIM</span> verifica que el contenido es auténtico y no se manipuló.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">DMARC</span> decide qué hacer si alguno de los dos falla, y te informa de los intentos de suplantación.</span><br />
</li>
</ul>
<br />
<span style="font-size: large;" class="mycode_size">Los tres cumplen funciones distintas, pero hoy en día se consideran complementarios — de hecho, DMARC depende técnicamente de que SPF o DKIM estén configurados para poder funcionar. Tener solo uno de los tres deja huecos que los otros dos cubrirían.</span><br />
 <br />
<hr class="mycode_hr" />
<br />
<span style="font-size: large;" class="mycode_size"><span style="color: #2980b9;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">Cómo comprobar si ya los tienes configurados</span></span></span><br />
 <br />
<ol type="1" class="mycode_list"><li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">MXToolbox</span> (mxtoolbox.com) — busca "SPF Record Lookup" y "DMARC Lookup", pega tu dominio.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">IntoDNS</span> (intodns.com) — análisis completo de tu DNS, incluyendo estos tres si están presentes.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Mail-Tester</span> (mail-tester.com) — la prueba más completa, porque envía un correo real y evalúa los tres a la vez con la configuración real de tu servidor.</span><br />
</li>
</ol>
 <br />
<hr class="mycode_hr" />
<br />
<span style="font-size: large;" class="mycode_size"><span style="color: #2980b9;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">Cómo configurarlos si te faltan</span></span></span><br />
<br />
<span style="font-size: large;" class="mycode_size">Los tres se configuran igual: añadiendo un registro TXT en el DNS de tu dominio (en cPanel: Dominios → Zone Editor / Editor de Zonas DNS).</span><br />
 <br />
<ol type="1" class="mycode_list"><li><span style="font-size: large;" class="mycode_size">Pregúntale a tu proveedor de email (Gmail/Google Workspace, tu hosting, etc.) qué valor exacto de SPF necesitas — cada proveedor de correo tiene el suyo propio.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Para DKIM, normalmente tu propio panel de correo (cPanel suele traerlo bajo "Email Deliverability" / "Autenticación de correo") genera automáticamente la clave y te da el registro exacto para pegar.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Para DMARC, empieza siempre con `p=none` durante unas semanas, revisa los informes que te lleguen, y solo entonces sube a `quarantine` o `reject`.</span><br />
</li>
</ol>
 <br />
<hr class="mycode_hr" />
<br />
<span style="font-size: large;" class="mycode_size"><span style="color: #2980b9;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">¿Cómo saber si Gmail confía en tus correos?</span></span></span><br />
<br />
<span style="font-size: large;" class="mycode_size">La forma más sencilla: envía un correo de prueba a una cuenta de Gmail y abre el mensaje → menú de tres puntos → **"Mostrar original"**.<br />
<br />
Ahí verás algo parecido a:</span><br />
 <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>SPF: PASS<br />
DKIM: PASS<br />
DMARC: PASS</code></div></div><br />
<span style="font-size: large;" class="mycode_size">Si alguno aparece como **<span style="font-weight: bold;" class="mycode_b">FAIL</span>**, tienes una pista clara de dónde está el problema — revisa esa sección concreta de esta guía.</span><br />
 <br />
<hr class="mycode_hr" />
<br />
<span style="font-size: x-large;" class="mycode_size"><span style="color: #c0392b;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">Error común: tener varios registros SPF</span></span></span><br />
<br />
<span style="font-size: large;" class="mycode_size">Muchos administradores añaden un SPF nuevo (por ejemplo, al configurar un nuevo proveedor de correo) sin eliminar el anterior. Esto rompe la validación por completo.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">Incorrecto (dos registros SPF separados):</span></span><br />
 <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>v=spf1 include:_spf.google.com ~all<br />
v=spf1 include:otroservicio.com ~all</code></div></div><br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Correcto (todo en un único registro):</span></span><br />
 <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>v=spf1 include:_spf.google.com include:otroservicio.com ~all</code></div></div><br />
<span style="font-size: large;" class="mycode_size">Solo debe existir **un único registro SPF por dominio** — si necesitas autorizar a varios proveedores de correo, se combinan todos dentro del mismo registro con varios `include:`, nunca en líneas separadas.</span><br />
 <br />
<hr class="mycode_hr" />
<br />
<span style="font-size: x-large;" class="mycode_size"><span style="color: #2980b9;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">Preguntas frecuentes</span></span></span><br />
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">¿Necesito los tres, o con uno solo basta?</span><br />
Cada proveedor de correo grande (Gmail, Outlook) valora positivamente tener los tres. Tener solo SPF ya ayuda, pero DKIM y DMARC cierran huecos que SPF no cubre por sí solo.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">¿Puedo romper algo si los configuro mal?</span><br />
Sí — un SPF mal escrito, o un DMARC en `reject` sin haber comprobado antes, puede hacer que tus propios correos legítimos empiecen a rebotar. Por eso se recomienda empezar siempre con la política más suave (`p=none` en DMARC) y subir de nivel solo tras confirmar que todo funciona.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">¿Esto evita que me suplanten por completo?</span><br />
Reduce mucho el riesgo, pero no es 100% infalible — depende también de que el servidor receptor respete tu política DMARC (la mayoría de proveedores grandes sí lo hacen).<br />
<br />
<span style="font-weight: bold;" class="mycode_b">¿Por qué mis correos de MyBB llegan a spam aunque el hosting diga que todo está bien?</span><br />
Es la causa más común de este problema: muchos hostings compartidos no configuran DKIM por defecto, o usan una IP compartida con mala reputación por otros clientes del mismo servidor. Comprobarlo con Mail-Tester te lo confirma de un vistazo.</span><br />
 <br />
<hr class="mycode_hr" />
<br />
<span style="font-size: large;" class="mycode_size"><span style="color: #2980b9;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">¿Y si SPF, DKIM y DMARC están bien pero sigo en spam?</span></span></span><br />
<br />
<span style="font-size: large;" class="mycode_size">Estos tres sistemas ayudan mucho, pero no son el único factor. Los grandes proveedores (Gmail, Outlook, Yahoo) también tienen en cuenta:</span><br />
 <ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size">La reputación de la IP que envía el correo (si esa misma IP la comparten otros clientes de tu hosting que hayan hecho spam antes, te afecta a ti también).</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">La antigüedad del dominio (un dominio recién creado empieza con menos confianza por defecto).</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Las quejas de spam recibidas contra tu dirección o dominio.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">El contenido del propio mensaje (palabras típicas de spam, exceso de enlaces, etc.).</span><br />
</li>
</ul>
<br />
<span style="font-size: large;" class="mycode_size">Por eso puede ocurrir que SPF, DKIM y DMARC estén perfectamente configurados y aun así algunos correos sigan llegando a spam — en ese caso, el problema ya no es de autenticación, sino de reputación general, que se construye con el tiempo enviando correos legítimos de forma constante.</span><br />
 <br />
<hr class="mycode_hr" />
<br />
<span style="font-size: x-large;" class="mycode_size"><span style="color: #27ae60;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">Conclusión</span></span></span><br />
<br />
<span style="font-size: large;" class="mycode_size">Estos tres sistemas no son solo "cosa de empresas grandes" — cualquier web que envíe correos (como un foro con activación de cuenta) se beneficia de tenerlos bien configurados. La forma más rápida de saber dónde estás: una prueba en Mail-Tester te dice en segundos qué de los tres te falta y qué corregir.</span>]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[Por qué Google no indexa mis páginas (7 causas y soluciones)]]></title>
			<link>https://phpost.es/tema-Tutorial-Por-qu%C3%A9-Google-no-indexa-mis-p%C3%A1ginas-7-causas-y-soluciones</link>
			<pubDate>Mon, 06 Jul 2026 22:39:46 +0200</pubDate>
			<dc:creator><![CDATA[<a href="https://phpost.es/member.php?action=profile&uid=1">Tronlar</a>]]></dc:creator>
			<guid isPermaLink="false">https://phpost.es/tema-Tutorial-Por-qu%C3%A9-Google-no-indexa-mis-p%C3%A1ginas-7-causas-y-soluciones</guid>
			<description><![CDATA[<span style="font-size: x-large;" class="mycode_size"><span style="color: #2980b9;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">Por qué Google no indexa mis páginas (7 causas y soluciones)</span></span></span><br />
<br />
<span style="font-size: large;" class="mycode_size">Has publicado contenido, pasan los días y esa página sigue sin aparecer en Google. Esta guía te ayuda a diagnosticar la causa real, en vez de adivinar.</span><br />
 <br />
<hr class="mycode_hr" />
<br />
<span style="color: #2980b9;" class="mycode_color"><span style="font-size: x-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Comprobación rápida</span></span></span><br />
<br />
<span style="font-size: large;" class="mycode_size">Busca en Google:</span><br />
 <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>site:tudominio.com URL-o-palabra-clave</code></div></div><br />
<span style="font-size: large;" class="mycode_size">Si no aparece ningún resultado, probablemente esa página no está indexada.</span><br />
<br />
<br />
<span style="font-size: x-large;" class="mycode_size"><span style="color: #2980b9;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">Diagnóstico: empieza por aquí</span></span></span><br />
<ol type="1" class="mycode_list"><li><span style="font-size: large;" class="mycode_size">Entra a <span style="font-weight: bold;" class="mycode_b">Google Search Console</span> → Inspección de URLs → pega la URL exacta que no indexa.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Mira qué dice arriba: "URL está en Google", "URL no está en Google" o un motivo concreto.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Ese mensaje te dice directamente en qué sección de este tutorial mirar.</span><br />
</li>
</ol>
<br />
<span style="font-size: large;" class="mycode_size"><span style="color: #2980b9;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">Resumen: mensaje de Search Console → qué significa</span></span></span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Bloqueada por robots.txt</span> → Google no puede rastrearla.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Excluida por noindex</span> → le estás diciendo tú mismo que no la indexe.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Google eligió otra canónica</span> → ve otra URL como la principal.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">No encontrada (404) / con redirección</span> → la URL no responde correctamente.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Rastreada, actualmente sin indexar</span> → Google la vio pero aún no decidió indexarla.</span><br />
</li>
</ul>
 <br />
<hr class="mycode_hr" />
<br />
<span style="font-size: large;" class="mycode_size"><span style="color: #2980b9;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">Causa 1: Google todavía no la ha rastreado</span></span></span><br />
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Síntoma en Search Console:</span> "URL no está en Google" → "Rastreada actualmente sin indexar" o directamente no aparece ningún dato.<br />
<br />
Es la causa más común y la menos preocupante — simplemente significa que Google todavía no ha pasado por ahí. Con una web nueva o poco conocida, esto puede tardar desde unos días hasta varias semanas.</span><br />
<br />
<span style="color: #27ae60;" class="mycode_color"><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Solución:</span></span></span><br />
<ol type="1" class="mycode_list"><li>En Inspección de URLs, pulsa <span style="font-weight: bold;" class="mycode_b">"Solicitar indexación"</span> — esto no garantiza que la indexe, pero adelanta la cola.<br />
</li>
<li>Asegúrate de tener un <span style="font-weight: bold;" class="mycode_b">sitemap.xml</span> enviado en Search Console (Sitemaps → Añadir sitemap nuevo).<br />
</li>
<li>Enlaza la página nueva desde otras páginas ya indexadas de tu web (Google encuentra contenido nuevo siguiendo enlaces).<br />
</li>
</ol>
 <br />
<hr class="mycode_hr" />
<br />
<span style="font-size: large;" class="mycode_size"><span style="color: #2980b9;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">Causa 2: robots.txt se lo está bloqueando</span></span></span><br />
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Síntoma en Search Console:</span> "Bloqueada por robots.txt".</span><br />
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Cómo comprobarlo:</span><br />
Entra a `tudominio.com/robots.txt` y busca líneas `Disallow:` que coincidan con la ruta de tu página. Por ejemplo, `Disallow: /foro/` bloquearía todo lo que empiece por esa ruta.</span><br />
<br />
<span style="color: #27ae60;" class="mycode_color"><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Solución:</span></span></span><br />
<span style="font-size: large;" class="mycode_size">Edita tu `<span style="font-weight: bold;" class="mycode_b">robots.txt</span>` y quita o ajusta la línea `<span style="font-weight: bold;" class="mycode_b">Disallow</span>` que esté bloqueando esa sección.<br />
Ten cuidado: a veces un `<span style="font-weight: bold;" class="mycode_b">robots.txt</span>` heredado de una instalación antigua bloquea carpetas enteras sin que el administrador actual lo sepa.</span><br />
 <br />
<hr class="mycode_hr" />
<br />
<span style="font-size: large;" class="mycode_size"><span style="color: #2980b9;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">Causa 3: tiene una etiqueta noindex</span></span></span><br />
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Síntoma en Search Console:</span> "Excluida por etiqueta 'noindex'".<br />
<br />
<span style="font-weight: bold;" class="mycode_b">Cómo comprobarlo:</span><br />
Mira el código fuente de la página (Ctrl+U) y busca:</span><br />
 <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>&lt;meta name="robots" content="noindex"&gt;</code></div></div><br />
<span style="color: #27ae60;" class="mycode_color"><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Solución:</span></span></span><br />
<span style="font-size: large;" class="mycode_size">Si esa etiqueta está puesta a propósito (por ejemplo, en páginas de administración o duplicadas), déjala — está haciendo su trabajo. Si aparece en contenido que sí quieres indexar, revisa tu plantilla: a veces un `noindex` se aplica por error a nivel global en vez de a una sección concreta.</span><br />
 <br />
<hr class="mycode_hr" />
<br />
<span style="font-size: large;" class="mycode_size"><span style="color: #2980b9;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">Causa 4: una URL canónica apunta a otro sitio</span></span></span><br />
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Síntoma en Search Console:</span> "Google eligió una URL canónica distinta a la del usuario".<br />
<br />
<span style="font-weight: bold;" class="mycode_b">Qué significa:</span> tu página tiene una etiqueta `&lt;link rel="canonical"&gt;` apuntando a otra URL, o Google ha decidido por su cuenta que otra versión (con o sin `www`, con o sin barra final, http vs https) es la "oficial", e ignora esta.<br />
<br />
<span style="color: #27ae60;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">Solución:</span></span><br />
Revisa el código fuente y busca la etiqueta `canonical` — confirma que apunta a la URL correcta, no a una versión antigua o a la home por error.</span><br />
 <br />
<hr class="mycode_hr" />
<br />
<span style="font-size: large;" class="mycode_size"><span style="color: #2980b9;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">Causa 5: contenido duplicado o demasiado escaso</span></span></span><br />
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Google no suele indexar páginas que:</span></span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size">Repiten casi el mismo contenido que otra página tuya (categorías vacías, páginas de filtro, paginación).</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Tienen muy poco texto único (un post de una sola frase, una página con solo una imagen).</span><br />
</li>
</ul>
<br />
<span style="color: #27ae60;" class="mycode_color"><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Solución:</span></span></span><br />
<span style="font-size: large;" class="mycode_size">No es tanto un "arreglo técnico" como un tema de contenido: cuantas más páginas finas o duplicadas tenga tu sitio, más disuade a Google de rastrear el resto ("crawl budget" limitado).<br />
Considera usar `noindex` tú mismo en páginas de filtro/paginación que no aportan contenido único, para que Google concentre su atención en lo que sí importa.</span><br />
 <br />
<hr class="mycode_hr" />
<br />
<span style="font-size: large;" class="mycode_size"><span style="color: #2980b9;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">Causa 6: la web es nueva y no tiene autoridad todavía</span></span><br />
<br />
Si tu dominio es reciente y con pocos enlaces externos apuntando a él, Google simplemente le da menos prioridad de rastreo. No es un error tuyo — es el mismo proceso por el que pasa cualquier web nueva.<br />
<br />
<span style="color: #27ae60;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">Lo que ayuda (sin trucos ni atajos):</span></span></span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size">Comparte tu web en foros, redes sociales o comunidades relacionadas (enlaces reales generan más visitas de Google indirectamente).</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Publica contenido con regularidad — Google rastrea más seguido las webs que actualizan a menudo.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Ten paciencia: para dominios nuevos, es normal que la indexación completa tarde semanas o meses.</span><br />
</li>
</ul>
 <br />
<hr class="mycode_hr" />
<br />
<span style="font-size: large;" class="mycode_size"><span style="color: #2980b9;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">Causa 7: la URL devuelve un error o redirige</span></span><br />
<br />
<span style="font-weight: bold;" class="mycode_b">Síntoma en Search Console:</span> "Página con redirección" o "No encontrada (404)".<br />
<br />
Si la URL devuelve un error 404, 410, o redirige a otra página, Google no va a indexar esa dirección concreta — indexará, como mucho, la URL final a la que redirige.</span><br />
<br />
<span style="color: #27ae60;" class="mycode_color"><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Solución:</span></span></span><br />
<span style="font-size: large;" class="mycode_size">Comprueba la URL exacta y verifica que devuelve código **200 OK** (puedes usar la misma Inspección de URLs de Search Console, o herramientas como httpstatus.io). Si la página se movió a propósito, asegúrate de que la redirección apunta a la URL nueva correcta y no a la home por defecto.</span><br />
 <br />
<hr class="mycode_hr" />
<br />
<span style="font-size: x-large;" class="mycode_size"><span style="color: #2980b9;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">Preguntas frecuentes</span></span></span><br />
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">¿Cuánto tarda Google en indexar una página nueva?</span><br />
Desde unas horas (webs muy activas y ya conocidas) hasta varias semanas (webs nuevas). No hay un plazo garantizado.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">¿Solicitar indexación en Search Console la indexa seguro?</span><br />
No, solo la pone en la cola de rastreo con más prioridad. Si Google decide que la página no aporta valor, puede seguir sin indexarla aunque la solicites.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">¿Por qué una página lleva meses indexada y de repente desaparece?</span><br />
Suele deberse a cambios en el contenido, un `noindex` añadido por error, un cambio de URL sin redirección, o una actualización del algoritmo de Google que reevaluó la calidad del contenido.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">¿El robots.txt afecta a lo ya indexado?</span><br />
No inmediatamente. Bloquear una URL en robots.txt impide que Google la rastree de nuevo, pero no borra automáticamente lo que ya tenía indexado — eso puede tardar en desaparecer, o requerir pedir su eliminación manualmente en Search Console.</span><br />
 <br />
<hr class="mycode_hr" />
<br />
<span style="font-size: x-large;" class="mycode_size"><span style="color: #27ae60;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">Conclusión</span></span></span><br />
<br />
<span style="font-size: large;" class="mycode_size">La mayoría de administradores pierden tiempo intentando "forzar" la indexación cuando el problema real ya aparece explicado en Search Console.<br />
<br />
Antes de tocar el robots.txt, plugins SEO o configuraciones avanzadas, revisa primero la Inspección de URLs. En la mayoría de casos, Google ya te está diciendo exactamente qué ocurre.<br />
<br />
¿Tienes un caso concreto que no encaja aquí? Responde en este mismo tema con la captura de lo que dice Search Console y lo vemos juntos.</span>]]></description>
			<content:encoded><![CDATA[<span style="font-size: x-large;" class="mycode_size"><span style="color: #2980b9;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">Por qué Google no indexa mis páginas (7 causas y soluciones)</span></span></span><br />
<br />
<span style="font-size: large;" class="mycode_size">Has publicado contenido, pasan los días y esa página sigue sin aparecer en Google. Esta guía te ayuda a diagnosticar la causa real, en vez de adivinar.</span><br />
 <br />
<hr class="mycode_hr" />
<br />
<span style="color: #2980b9;" class="mycode_color"><span style="font-size: x-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Comprobación rápida</span></span></span><br />
<br />
<span style="font-size: large;" class="mycode_size">Busca en Google:</span><br />
 <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>site:tudominio.com URL-o-palabra-clave</code></div></div><br />
<span style="font-size: large;" class="mycode_size">Si no aparece ningún resultado, probablemente esa página no está indexada.</span><br />
<br />
<br />
<span style="font-size: x-large;" class="mycode_size"><span style="color: #2980b9;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">Diagnóstico: empieza por aquí</span></span></span><br />
<ol type="1" class="mycode_list"><li><span style="font-size: large;" class="mycode_size">Entra a <span style="font-weight: bold;" class="mycode_b">Google Search Console</span> → Inspección de URLs → pega la URL exacta que no indexa.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Mira qué dice arriba: "URL está en Google", "URL no está en Google" o un motivo concreto.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Ese mensaje te dice directamente en qué sección de este tutorial mirar.</span><br />
</li>
</ol>
<br />
<span style="font-size: large;" class="mycode_size"><span style="color: #2980b9;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">Resumen: mensaje de Search Console → qué significa</span></span></span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Bloqueada por robots.txt</span> → Google no puede rastrearla.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Excluida por noindex</span> → le estás diciendo tú mismo que no la indexe.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Google eligió otra canónica</span> → ve otra URL como la principal.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">No encontrada (404) / con redirección</span> → la URL no responde correctamente.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Rastreada, actualmente sin indexar</span> → Google la vio pero aún no decidió indexarla.</span><br />
</li>
</ul>
 <br />
<hr class="mycode_hr" />
<br />
<span style="font-size: large;" class="mycode_size"><span style="color: #2980b9;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">Causa 1: Google todavía no la ha rastreado</span></span></span><br />
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Síntoma en Search Console:</span> "URL no está en Google" → "Rastreada actualmente sin indexar" o directamente no aparece ningún dato.<br />
<br />
Es la causa más común y la menos preocupante — simplemente significa que Google todavía no ha pasado por ahí. Con una web nueva o poco conocida, esto puede tardar desde unos días hasta varias semanas.</span><br />
<br />
<span style="color: #27ae60;" class="mycode_color"><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Solución:</span></span></span><br />
<ol type="1" class="mycode_list"><li>En Inspección de URLs, pulsa <span style="font-weight: bold;" class="mycode_b">"Solicitar indexación"</span> — esto no garantiza que la indexe, pero adelanta la cola.<br />
</li>
<li>Asegúrate de tener un <span style="font-weight: bold;" class="mycode_b">sitemap.xml</span> enviado en Search Console (Sitemaps → Añadir sitemap nuevo).<br />
</li>
<li>Enlaza la página nueva desde otras páginas ya indexadas de tu web (Google encuentra contenido nuevo siguiendo enlaces).<br />
</li>
</ol>
 <br />
<hr class="mycode_hr" />
<br />
<span style="font-size: large;" class="mycode_size"><span style="color: #2980b9;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">Causa 2: robots.txt se lo está bloqueando</span></span></span><br />
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Síntoma en Search Console:</span> "Bloqueada por robots.txt".</span><br />
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Cómo comprobarlo:</span><br />
Entra a `tudominio.com/robots.txt` y busca líneas `Disallow:` que coincidan con la ruta de tu página. Por ejemplo, `Disallow: /foro/` bloquearía todo lo que empiece por esa ruta.</span><br />
<br />
<span style="color: #27ae60;" class="mycode_color"><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Solución:</span></span></span><br />
<span style="font-size: large;" class="mycode_size">Edita tu `<span style="font-weight: bold;" class="mycode_b">robots.txt</span>` y quita o ajusta la línea `<span style="font-weight: bold;" class="mycode_b">Disallow</span>` que esté bloqueando esa sección.<br />
Ten cuidado: a veces un `<span style="font-weight: bold;" class="mycode_b">robots.txt</span>` heredado de una instalación antigua bloquea carpetas enteras sin que el administrador actual lo sepa.</span><br />
 <br />
<hr class="mycode_hr" />
<br />
<span style="font-size: large;" class="mycode_size"><span style="color: #2980b9;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">Causa 3: tiene una etiqueta noindex</span></span></span><br />
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Síntoma en Search Console:</span> "Excluida por etiqueta 'noindex'".<br />
<br />
<span style="font-weight: bold;" class="mycode_b">Cómo comprobarlo:</span><br />
Mira el código fuente de la página (Ctrl+U) y busca:</span><br />
 <br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>&lt;meta name="robots" content="noindex"&gt;</code></div></div><br />
<span style="color: #27ae60;" class="mycode_color"><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Solución:</span></span></span><br />
<span style="font-size: large;" class="mycode_size">Si esa etiqueta está puesta a propósito (por ejemplo, en páginas de administración o duplicadas), déjala — está haciendo su trabajo. Si aparece en contenido que sí quieres indexar, revisa tu plantilla: a veces un `noindex` se aplica por error a nivel global en vez de a una sección concreta.</span><br />
 <br />
<hr class="mycode_hr" />
<br />
<span style="font-size: large;" class="mycode_size"><span style="color: #2980b9;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">Causa 4: una URL canónica apunta a otro sitio</span></span></span><br />
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Síntoma en Search Console:</span> "Google eligió una URL canónica distinta a la del usuario".<br />
<br />
<span style="font-weight: bold;" class="mycode_b">Qué significa:</span> tu página tiene una etiqueta `&lt;link rel="canonical"&gt;` apuntando a otra URL, o Google ha decidido por su cuenta que otra versión (con o sin `www`, con o sin barra final, http vs https) es la "oficial", e ignora esta.<br />
<br />
<span style="color: #27ae60;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">Solución:</span></span><br />
Revisa el código fuente y busca la etiqueta `canonical` — confirma que apunta a la URL correcta, no a una versión antigua o a la home por error.</span><br />
 <br />
<hr class="mycode_hr" />
<br />
<span style="font-size: large;" class="mycode_size"><span style="color: #2980b9;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">Causa 5: contenido duplicado o demasiado escaso</span></span></span><br />
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Google no suele indexar páginas que:</span></span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size">Repiten casi el mismo contenido que otra página tuya (categorías vacías, páginas de filtro, paginación).</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Tienen muy poco texto único (un post de una sola frase, una página con solo una imagen).</span><br />
</li>
</ul>
<br />
<span style="color: #27ae60;" class="mycode_color"><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Solución:</span></span></span><br />
<span style="font-size: large;" class="mycode_size">No es tanto un "arreglo técnico" como un tema de contenido: cuantas más páginas finas o duplicadas tenga tu sitio, más disuade a Google de rastrear el resto ("crawl budget" limitado).<br />
Considera usar `noindex` tú mismo en páginas de filtro/paginación que no aportan contenido único, para que Google concentre su atención en lo que sí importa.</span><br />
 <br />
<hr class="mycode_hr" />
<br />
<span style="font-size: large;" class="mycode_size"><span style="color: #2980b9;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">Causa 6: la web es nueva y no tiene autoridad todavía</span></span><br />
<br />
Si tu dominio es reciente y con pocos enlaces externos apuntando a él, Google simplemente le da menos prioridad de rastreo. No es un error tuyo — es el mismo proceso por el que pasa cualquier web nueva.<br />
<br />
<span style="color: #27ae60;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">Lo que ayuda (sin trucos ni atajos):</span></span></span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size">Comparte tu web en foros, redes sociales o comunidades relacionadas (enlaces reales generan más visitas de Google indirectamente).</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Publica contenido con regularidad — Google rastrea más seguido las webs que actualizan a menudo.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Ten paciencia: para dominios nuevos, es normal que la indexación completa tarde semanas o meses.</span><br />
</li>
</ul>
 <br />
<hr class="mycode_hr" />
<br />
<span style="font-size: large;" class="mycode_size"><span style="color: #2980b9;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">Causa 7: la URL devuelve un error o redirige</span></span><br />
<br />
<span style="font-weight: bold;" class="mycode_b">Síntoma en Search Console:</span> "Página con redirección" o "No encontrada (404)".<br />
<br />
Si la URL devuelve un error 404, 410, o redirige a otra página, Google no va a indexar esa dirección concreta — indexará, como mucho, la URL final a la que redirige.</span><br />
<br />
<span style="color: #27ae60;" class="mycode_color"><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Solución:</span></span></span><br />
<span style="font-size: large;" class="mycode_size">Comprueba la URL exacta y verifica que devuelve código **200 OK** (puedes usar la misma Inspección de URLs de Search Console, o herramientas como httpstatus.io). Si la página se movió a propósito, asegúrate de que la redirección apunta a la URL nueva correcta y no a la home por defecto.</span><br />
 <br />
<hr class="mycode_hr" />
<br />
<span style="font-size: x-large;" class="mycode_size"><span style="color: #2980b9;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">Preguntas frecuentes</span></span></span><br />
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">¿Cuánto tarda Google en indexar una página nueva?</span><br />
Desde unas horas (webs muy activas y ya conocidas) hasta varias semanas (webs nuevas). No hay un plazo garantizado.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">¿Solicitar indexación en Search Console la indexa seguro?</span><br />
No, solo la pone en la cola de rastreo con más prioridad. Si Google decide que la página no aporta valor, puede seguir sin indexarla aunque la solicites.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">¿Por qué una página lleva meses indexada y de repente desaparece?</span><br />
Suele deberse a cambios en el contenido, un `noindex` añadido por error, un cambio de URL sin redirección, o una actualización del algoritmo de Google que reevaluó la calidad del contenido.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">¿El robots.txt afecta a lo ya indexado?</span><br />
No inmediatamente. Bloquear una URL en robots.txt impide que Google la rastree de nuevo, pero no borra automáticamente lo que ya tenía indexado — eso puede tardar en desaparecer, o requerir pedir su eliminación manualmente en Search Console.</span><br />
 <br />
<hr class="mycode_hr" />
<br />
<span style="font-size: x-large;" class="mycode_size"><span style="color: #27ae60;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">Conclusión</span></span></span><br />
<br />
<span style="font-size: large;" class="mycode_size">La mayoría de administradores pierden tiempo intentando "forzar" la indexación cuando el problema real ya aparece explicado en Search Console.<br />
<br />
Antes de tocar el robots.txt, plugins SEO o configuraciones avanzadas, revisa primero la Inspección de URLs. En la mayoría de casos, Google ya te está diciendo exactamente qué ocurre.<br />
<br />
¿Tienes un caso concreto que no encaja aquí? Responde en este mismo tema con la captura de lo que dice Search Console y lo vemos juntos.</span>]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[77 herramientas gratuitas para administradores web (SEO, VPS y seguridad)]]></title>
			<link>https://phpost.es/tema-Tutorial-77-herramientas-gratuitas-para-administradores-web-SEO-VPS-y-seguridad</link>
			<pubDate>Sun, 05 Jul 2026 19:54:52 +0200</pubDate>
			<dc:creator><![CDATA[<a href="https://phpost.es/member.php?action=profile&uid=1">Tronlar</a>]]></dc:creator>
			<guid isPermaLink="false">https://phpost.es/tema-Tutorial-77-herramientas-gratuitas-para-administradores-web-SEO-VPS-y-seguridad</guid>
			<description><![CDATA[<span style="font-size: x-large;" class="mycode_size"><span style="color: #2980b9;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">77 herramientas gratuitas para administradores web (SEO, VPS y seguridad)</span></span></span><br />
<br />
<br />
<span style="font-size: large;" class="mycode_size">Administrar una web moderna implica vigilar la seguridad, el rendimiento, el SEO, las copias de seguridad, el correo, los DNS y muchas otras tareas a la vez. Tanto si administras un foro, un blog, una tienda online, un VPS, o trabajas como webmaster o administrador de sistemas, existen herramientas gratuitas que ayudan a detectar problemas, automatizar tareas y ahorrar dinero en hosting — muchas de ellas pueden utilizarse sin experiencia avanzada.<br />
<br />
En esta guía encontrarás 77 herramientas gratuitas organizadas por categorías, numeradas consecutivamente del 1 al 77 para facilitar su consulta. La mayoría de administradores solo utilizarán entre 5 y 15 de esta lista de forma habitual — el resto quedan aquí para cuando te surja esa necesidad concreta.</span><br />
 <br />
<hr class="mycode_hr" />
<br />
<span style="font-size: x-large;" class="mycode_size"><span style="color: #2980b9;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">Resumen: qué herramienta según tu necesidad</span></span></span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">SEO</span> → Google Search Console</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Velocidad</span> → GTmetrix</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Seguridad</span> → VirusTotal</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Monitorización</span> → UptimeRobot</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Correo</span> → Mail-Tester</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">DNS</span> → Cloudflare</span><br />
</li>
</ul>
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Si administras un foro con Risus Nova</span>, estas son las que más te van a servir de toda la lista:</span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size">Cloudflare Turnstile — corta bots de registro sin molestar a usuarios reales.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Google Search Console — para saber si Google indexa bien tus posts y comunidades.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Cloudflare — protección y velocidad, sin tocar tu hosting.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">UptimeRobot — te avisa si el foro se cae.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Mail-Tester — para que las notificaciones y verificaciones de registro no acaben en spam.</span><br />
</li>
</ul>
 <br />
<hr class="mycode_hr" />
<br />
<span style="font-size: x-large;" class="mycode_size"><span style="color: #2980b9;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">Índice</span></span></span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size">Seguridad</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Rendimiento y velocidad</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Monitorización y uptime</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">SEO</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Correo electrónico</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Optimización de imágenes</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Backups y automatización</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Gestión de servidor y archivos</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Bases de datos</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Linux y VPS</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Testing y desarrollo</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">DNS y dominios</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">IA para administradores web</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Productividad</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Otros útiles</span><br />
</li>
</ul>
 <br />
<hr class="mycode_hr" />
<br />
<span style="font-size: x-large;" class="mycode_size"><span style="color: #2980b9;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">¿Qué problema tienes ahora mismo?</span></span></span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Mi web va lenta</span> → GTmetrix, PageSpeed Insights, WebPageTest.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">No sé si Google indexa bien mi web</span> → Google Search Console.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Mi correo no llega o cae en spam</span> → Mail-Tester, MXToolbox.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Tengo miedo de malware o phishing</span> → VirusTotal, Sucuri SiteCheck.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Mi web se cae y no me entero</span> → UptimeRobot, StatusCake.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">No sé si mi SSL está bien configurado</span> → Qualys SSL Labs.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Quiero hacer copias de seguridad automáticas</span> → UpdraftPlus, Cron-job.org.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Administro un VPS y quiero vigilarlo mejor</span> → htop, fail2ban, Webmin.</span><br />
</li>
</ul>
 <br />
<hr class="mycode_hr" />
<br />
<span style="font-size: x-large;" class="mycode_size"><span style="color: #2980b9;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">Si solo pudiera recomendar 10, serían estas</span></span></span><br />
<ol type="1" class="mycode_list"><li><span style="font-size: large;" class="mycode_size">Google Search Console</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Cloudflare</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">UptimeRobot</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">VirusTotal</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">GTmetrix</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">FileZilla</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">MXToolbox</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">TinyPNG</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Qualys SSL Labs</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">ChatGPT</span><br />
</li>
</ol>
<br />
<span style="font-size: large;" class="mycode_size">Si eres nuevo administrando una web, empieza por estas diez y no te compliques con el resto hasta que realmente las necesites.<br />
<br />
Con estas 10 ya cubres seguridad básica, velocidad, SEO, correo y monitorización. El resto de la lista son herramientas para necesidades más concretas.</span><br />
<br />
<br />
<span style="font-size: x-large;" class="mycode_size"><span style="color: #2980b9;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">Recomendaciones según tu proyecto</span></span></span><br />
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Si tienes un blog:</span></span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size">Google Search Console</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Google Analytics</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Cloudflare</span><br />
</li>
</ul>
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Si tienes un foro o comunidad:</span></span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size">UptimeRobot</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Cloudflare</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">MXToolbox</span><br />
</li>
</ul>
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Si administras un VPS:</span></span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size">htop</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">fail2ban</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Webmin</span><br />
</li>
</ul>
 <br />
<hr class="mycode_hr" />
<br />
<span style="font-size: x-large;" class="mycode_size"><span style="color: #2980b9;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">Seguridad</span></span></span><br />
<ol type="1" class="mycode_list"><li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">VirusTotal</span> ⭐⭐⭐⭐⭐ — analiza archivos y URLs con decenas de motores antivirus a la vez, útil para comprobar un enlace sospechoso o un archivo antes de subirlo a tu servidor.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Sucuri SiteCheck</span> ⭐⭐⭐⭐ — escanea tu web en busca de malware, listas negras y código inyectado, sin instalar nada.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Qualys SSL Labs (SSL Test)</span> ⭐⭐⭐⭐⭐ — analiza la configuración SSL/TLS de tu dominio y te da una nota de la A a la F, con el detalle de qué falla.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Let's Encrypt</span> ⭐⭐⭐⭐ — certificados SSL gratuitos con renovación automática, el estándar actual para tener HTTPS sin coste.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Have I Been Pwned</span> ⭐⭐⭐⭐ — comprueba si un email tuyo o de tus usuarios ha aparecido en alguna filtración de datos conocida.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">OWASP ZAP</span> ⭐⭐⭐ — escáner de vulnerabilidades web de código abierto, más orientado a quien quiera auditar su propia web a fondo.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">SecurityHeaders</span> ⭐⭐⭐⭐ — analiza las cabeceras de seguridad HTTP de tu web (CSP, HSTS, etc.) y te dice qué te falta.</span><br />
</li>
</ol>
<br />
<span style="font-size: x-large;" class="mycode_size"><span style="color: #2980b9;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">Rendimiento y velocidad</span></span></span><br />
<ol type="1" class="mycode_list"><li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Google PageSpeed Insights</span> ⭐⭐⭐⭐ — mide la velocidad de carga en móvil y escritorio, con recomendaciones concretas priorizadas por impacto.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">GTmetrix</span> ⭐⭐⭐⭐ — desglosa exactamente qué recursos frenan tu web (imágenes, scripts, servidor lento...).</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">WebPageTest</span> ⭐⭐⭐ — pruebas de velocidad desde ubicaciones y navegadores reales de todo el mundo, más técnico que los anteriores.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Chrome DevTools (Lighthouse)</span> ⭐⭐⭐⭐ — auditoría de rendimiento, accesibilidad y SEO integrada directamente en el navegador, sin salir de él.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Pingdom Website Speed Test</span> ⭐⭐⭐ — prueba de velocidad rápida y sencilla, buena como segunda opinión.</span><br />
</li>
</ol>
<br />
<span style="font-size: x-large;" class="mycode_size"><span style="color: #2980b9;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">Monitorización y uptime</span></span></span><br />
<ol type="1" class="mycode_list"><li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">UptimeRobot</span> ⭐⭐⭐⭐⭐ — te avisa por email/SMS si tu web se cae, gratis hasta 50 monitores cada 5 minutos.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">StatusCake</span> ⭐⭐⭐⭐ — alternativa a UptimeRobot, con plan gratuito permanente y buenas alertas.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Freshping</span> ⭐⭐⭐ — monitorización gratuita de Freshworks, sencilla de configurar.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Cronitor</span> ⭐⭐⭐ — pensada específicamente para vigilar que tus tareas cron se ejecuten a tiempo, no solo si la web está caída.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Netdata</span> ⭐⭐⭐⭐ — monitorización en tiempo real de CPU, memoria y disco de tu servidor, con panel visual muy detallado, gratis para un solo nodo.</span><br />
</li>
</ol>
<br />
<span style="font-size: x-large;" class="mycode_size"><span style="color: #2980b9;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">SEO</span></span></span><br />
<ol type="1" class="mycode_list"><li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Google Search Console</span> ⭐⭐⭐⭐⭐ — imprescindible: te muestra exactamente cómo ve Google tu sitio, qué páginas indexa y qué errores encuentra.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Google Analytics</span> ⭐⭐⭐⭐ — estadísticas reales de visitas y comportamiento de usuarios, la referencia del sector.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Bing Webmaster Tools</span> ⭐⭐⭐ — lo mismo que Search Console pero para Bing, menos tráfico pero se configura en 5 minutos.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Screaming Frog SEO Spider</span> ⭐⭐⭐⭐ — rastrea tu web como lo haría un buscador, gratis hasta 500 URLs, ideal para encontrar enlaces rotos o títulos duplicados.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Ubersuggest</span> ⭐⭐⭐ — ideas de palabras clave, versión gratuita con búsquedas diarias limitadas.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">AnswerThePublic</span> ⭐⭐⭐ — muestra preguntas reales que la gente busca sobre un tema, útil para elegir de qué escribir.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Google Trends</span> ⭐⭐⭐⭐ — descubre tendencias de búsqueda y compara el interés entre distintos temas a lo largo del tiempo.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Matomo</span> ⭐⭐⭐⭐ — alternativa a Google Analytics que respeta más la privacidad de tus usuarios, puedes alojarla tú mismo.</span><br />
</li>
</ol>
<br />
<span style="font-size: x-large;" class="mycode_size"><span style="color: #2980b9;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">Correo electrónico</span></span></span><br />
<ol type="1" class="mycode_list"><li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Mail-Tester</span> ⭐⭐⭐⭐⭐ — te da una puntuación sobre 10 de si tus correos van a llegar a la bandeja de entrada o a spam, y por qué.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">MXToolbox</span> ⭐⭐⭐⭐ — comprobación de registros MX, si tu dominio está en alguna lista negra de spam, y mucho más.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">SPF Record Generator</span> ⭐⭐⭐⭐ — genera el registro SPF correcto para que tu dominio no sea usado para suplantar correos.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">DMARC Analyzer</span> ⭐⭐⭐ — analiza tu configuración DMARC, el último paso para tener el correo de tu dominio bien protegido.</span><br />
</li>
</ol>
<br />
<span style="font-size: x-large;" class="mycode_size"><span style="color: #2980b9;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">Optimización de imágenes</span></span></span><br />
<ol type="1" class="mycode_list"><li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">TinyPNG</span> ⭐⭐⭐⭐⭐ — comprime PNG/JPG sin pérdida visible de calidad, en segundos.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Squoosh</span> ⭐⭐⭐⭐ — compresor de imágenes de Google, funciona todo en el navegador sin subir nada a ningún servidor.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Compressor.io</span> ⭐⭐⭐ — otra alternativa online de compresión, con más control manual sobre la calidad.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">ImageOptim</span> (Mac) ⭐⭐⭐⭐ — optimización de imágenes nativa y automática para quien trabaje en macOS.</span><br />
</li>
</ol>
<br />
<span style="font-size: x-large;" class="mycode_size"><span style="color: #2980b9;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">Backups y automatización</span></span></span><br />
<ol type="1" class="mycode_list"><li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">UpdraftPlus</span> ⭐⭐⭐⭐ — copias de seguridad automáticas con la versión gratuita más completa del mercado.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Cron-job.org</span> ⭐⭐⭐⭐ — programador de tareas cron gratuito en la nube, útil si tu hosting no te deja configurarlas cómodamente.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">rclone</span> ⭐⭐⭐ — sincroniza tus backups automáticamente con Google Drive, Dropbox y similares.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Rsync</span> ⭐⭐⭐ — la herramienta clásica de sincronización/backups en Linux, para quien maneje terminal.</span><br />
</li>
</ol>
<br />
<span style="font-size: x-large;" class="mycode_size"><span style="color: #2980b9;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">Gestión de servidor y archivos</span></span></span><br />
<ol type="1" class="mycode_list"><li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">phpMyAdmin</span> ⭐⭐⭐⭐ — gestión visual de bases de datos MySQL, viene preinstalado en la mayoría de hostings.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Adminer</span> ⭐⭐⭐⭐ — alternativa ligera a phpMyAdmin, cabe en un solo archivo PHP, ideal si tu hosting no lo trae.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Webmin</span> ⭐⭐⭐ — panel de administración completo para servidores Linux, para quien tenga un VPS.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">FileZilla</span> ⭐⭐⭐⭐ — cliente FTP/SFTP gratuito y multiplataforma, el más usado del sector.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">WinSCP</span> ⭐⭐⭐⭐ — cliente SFTP/SCP para Windows, alternativa a FileZilla.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">htop</span> ⭐⭐⭐ — monitor de procesos en Linux, mucho más visual que el clásico `top`.</span><br />
</li>
</ol>
<br />
<span style="font-size: x-large;" class="mycode_size"><span style="color: #2980b9;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">Bases de datos</span></span></span><br />
<ol type="1" class="mycode_list"><li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">DBeaver</span> ⭐⭐⭐⭐ — gestor visual de bases de datos multiplataforma, más potente que phpMyAdmin para trabajo avanzado.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">HeidiSQL</span> ⭐⭐⭐⭐ — cliente MySQL ligero y gratuito para Windows, muy usado por su sencillez.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">MySQL Workbench</span> ⭐⭐⭐ — herramienta oficial de MySQL, incluye diseño visual de bases de datos además de gestión.</span><br />
</li>
</ol>
<br />
<span style="font-size: x-large;" class="mycode_size"><span style="color: #2980b9;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">Linux y VPS</span></span></span><br />
<ol type="1" class="mycode_list"><li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">fail2ban</span> ⭐⭐⭐⭐⭐ — bloquea automáticamente IPs que intentan acceder por fuerza bruta (SSH, login, etc.).</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">btop</span> ⭐⭐⭐⭐ — monitor de recursos del sistema con una interfaz visual moderna, evolución de htop.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">tmux</span> ⭐⭐⭐ — permite mantener sesiones de terminal abiertas aunque se corte la conexión SSH.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">ncdu</span> ⭐⭐⭐⭐ — te muestra visualmente qué carpetas ocupan más espacio en tu servidor, ideal cuando se llena el disco.</span><br />
</li>
</ol>
<br />
<span style="font-size: x-large;" class="mycode_size"><span style="color: #2980b9;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">Testing y desarrollo</span></span></span><br />
<ol type="1" class="mycode_list"><li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Postman</span> ⭐⭐⭐⭐ — pruebas de APIs con plan gratuito muy completo, estándar en el sector.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">ngrok</span> ⭐⭐⭐ — expone tu servidor local a internet temporalmente, útil para probar webhooks sin subir nada a producción.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">3v4l.org</span> ⭐⭐⭐⭐ — prueba un mismo código PHP en varias versiones a la vez, perfecto para comprobar compatibilidad antes de actualizar PHP.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Regex101</span> ⭐⭐⭐ — prueba expresiones regulares en tiempo real, con explicación de cada parte del patrón.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">JSONLint</span> ⭐⭐⭐ — valida y da formato a JSON cuando algo no carga y sospechas que el formato está mal.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">CyberChef</span> ⭐⭐⭐⭐ — "la navaja suiza" para codificar, decodificar, cifrar o transformar texto y datos, todo en el navegador.</span><br />
</li>
</ol>
<br />
<span style="font-size: x-large;" class="mycode_size"><span style="color: #2980b9;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">DNS y dominios</span></span></span><br />
<ol type="1" class="mycode_list"><li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">IntoDNS</span> ⭐⭐⭐⭐ — análisis completo de la salud de tu configuración DNS, detecta errores comunes de un vistazo.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">DNS Checker</span> ⭐⭐⭐⭐ — ver si un cambio de DNS ya se ha propagado globalmente, evita la duda de "¿por qué no veo el cambio todavía?".</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">WHOIS Lookup</span> ⭐⭐⭐ — información pública de registro de un dominio (cuándo caduca, quién lo gestiona).</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Cloudflare</span> (plan gratuito) ⭐⭐⭐⭐⭐ — DNS ultrarrápido, CDN global, protección contra ataques, caché y optimización de rendimiento, todo junto. Probablemente la mejora gratuita con más impacto que puede aplicar una web pequeña o mediana.</span><br />
</li>
</ol>
<br />
<span style="font-size: x-large;" class="mycode_size"><span style="color: #2980b9;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">Anti-spam y moderación (para foros y comunidades)</span></span></span><br />
<br />
<span style="font-size: large;" class="mycode_size">Si administras un foro como Risus Nova en vez de un blog, estas te van a servir más que muchas de las genéricas de la lista.</span><br />
<ol type="1" class="mycode_list"><li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Cloudflare Turnstile</span> ⭐⭐⭐⭐⭐ — alternativa gratuita a reCAPTCHA, no molesta al usuario con puzzles y detecta bots a nivel de red.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">reCAPTCHA (v3)</span> ⭐⭐⭐⭐ — el clásico de Google, analiza el comportamiento en vez de pedir un puzzle visible.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Akismet</span> ⭐⭐⭐⭐ — filtro anti-spam para comentarios/posts entrenado con datos de millones de sitios, gratis para uso personal.</span><br />
</li>
</ol>
<br />
<span style="font-size: x-large;" class="mycode_size"><span style="color: #2980b9;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">IA para administradores web</span></span></span><br />
<br />
<span style="font-size: large;" class="mycode_size">No para generar spam ni contenido automático de mala calidad, sino como apoyo real para documentación, soporte y análisis de código.</span><br />
<ol type="1" class="mycode_list"><li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">ChatGPT</span> ⭐⭐⭐⭐ — útil para depurar errores, generar documentación o explicar código que no es tuyo.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Claude</span> ⭐⭐⭐⭐ — buena opción para trabajar con archivos largos (CSS/JS completos) y para tareas de edición de código con contexto amplio.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Gemini</span> ⭐⭐⭐ — integrado con el ecosistema de Google, útil si ya usas Search Console/Analytics a diario.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Perplexity</span> ⭐⭐⭐ — más orientado a búsqueda con fuentes citadas, útil para investigar antes de tomar una decisión técnica.</span><br />
</li>
</ol>
<br />
<span style="font-size: x-large;" class="mycode_size"><span style="color: #2980b9;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">Productividad</span></span></span><br />
<br />
<span style="font-size: large;" class="mycode_size">Muchos administradores llevan su proyecto solos — estas ayudan a organizarse.</span><br />
<ol type="1" class="mycode_list"><li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Obsidian</span> ⭐⭐⭐⭐ — notas en texto plano enlazadas entre sí, muy usado para documentar procesos técnicos propios.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Notion</span> ⭐⭐⭐⭐ — organización de tareas, notas y documentación en un solo sitio, con plan gratuito generoso.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Trello</span> ⭐⭐⭐ — tableros tipo kanban para llevar el seguimiento de tareas pendientes del proyecto.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Joplin</span> ⭐⭐⭐ — alternativa de notas de código abierto, con cifrado y sincronización propia.</span><br />
</li>
</ol>
<br />
<span style="font-size: x-large;" class="mycode_size"><span style="color: #2980b9;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">Otros útiles</span></span></span><br />
<ol type="1" class="mycode_list"><li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">W3C Validator</span> ⭐⭐⭐ — comprueba que tu HTML/CSS cumple los estándares oficiales.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Can I Use</span> ⭐⭐⭐⭐ — compatibilidad de funciones web según el navegador, antes de usar algo muy nuevo en CSS/JS.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Diffchecker</span> ⭐⭐⭐⭐ — compara dos textos o archivos y resalta las diferencias línea por línea.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">TinyURL</span> ⭐⭐⭐ — acortador de enlaces gratuito y sencillo, sin necesidad de cuenta.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Wayback Machine</span> (archive.org) ⭐⭐⭐⭐ — consulta versiones antiguas de cualquier web, útil para recuperar contenido perdido.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Google Safe Browsing Transparency Report</span> ⭐⭐⭐⭐ — comprueba si un sitio (el tuyo u otro) está marcado como peligroso por Google.</span><br />
</li>
</ol>
 <br />
<hr class="mycode_hr" />
<br />
<span style="font-size: x-large;" class="mycode_size"><span style="color: #2980b9;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">Problemas habituales y herramienta recomendada</span></span></span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size">Mi web va lenta → GTmetrix</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Mis correos llegan a spam → Mail-Tester</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Google no indexa mis páginas → Search Console</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">No sé por qué mi servidor consume tanta RAM → htop</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Mi SSL da errores → SSL Labs</span><br />
</li>
</ul>
 <br />
<hr class="mycode_hr" />
<br />
<span style="font-size: x-large;" class="mycode_size"><span style="color: #c0392b;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">Errores comunes</span></span></span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size">❌ Instalar herramientas porque sí, sin tener un problema real que resolver.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">❌ Configurar Cloudflare sin entender antes cómo funciona tu DNS.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">❌ Ignorar Search Console durante meses sin revisar los errores que reporta.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">❌ No probar nunca si tus backups realmente se pueden restaurar.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">❌ No revisar las alertas de uptime hasta que ya llevas horas caído.</span><br />
</li>
</ul>
 <br />
<hr class="mycode_hr" />
<br />
<span style="font-size: x-large;" class="mycode_size"><span style="color: #2980b9;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">Preguntas frecuentes</span></span></span><br />
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">¿Cuál es la mejor herramienta SEO gratuita?</span><br />
Google Search Console, sin discusión — te dice exactamente cómo ve Google tu sitio.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">¿Qué herramienta gratuita sirve para saber si una web está caída?</span><br />
UptimeRobot, gratis hasta 50 monitores.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">¿Qué herramienta gratuita sirve para analizar SSL?</span><br />
Qualys SSL Labs.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">¿Cuál es la mejor herramienta para comprobar DNS?</span><br />
IntoDNS para un chequeo completo, o MXToolbox si el problema es específico del correo.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">¿Uso Cloudflare o solo cambio el hosting?</span><br />
Ambas cosas cumplen funciones distintas: Cloudflare protege y acelera tu web sin cambiar de hosting, es casi siempre la primera mejora que merece la pena hacer.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">¿Necesito usar todas estas herramientas?</span><br />
No. La mayoría de administradores utilizan menos de diez de forma habitual.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">¿Qué herramientas instalar primero en una web nueva?</span><br />
Search Console, Cloudflare, UptimeRobot y una solución de copias de seguridad.</span><br />
 <br />
<hr class="mycode_hr" />
<br />
<span style="font-size: x-large;" class="mycode_size"><span style="color: #2980b9;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">Tutoriales relacionados de Risus Nova</span></span></span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size">Cómo publicar un producto en el Catálogo de Ventas</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Cómo funcionan los Posts Conjuntos (coautoría)</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Autoguardado y recuperación de Borradores</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Cómo añadir una encuesta a tu post</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Error 500, 403 y 404 — diagnóstico rápido y soluciones</span><br />
</li>
</ul>
 <br />
<hr class="mycode_hr" />
<br />
<span style="font-size: x-large;" class="mycode_size"><span style="color: #27ae60;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">Conclusión</span></span></span><br />
<br />
<span style="font-size: large;" class="mycode_size">No necesitas utilizar las 77 herramientas. De hecho, la mayoría de administradores gestionan sus proyectos con menos de 10. Lo importante es conocer qué problema quieres resolver y saber qué herramienta puede ayudarte cuando llegue el momento.<br />
<br />
Si estás empezando, configura primero Search Console, Cloudflare, UptimeRobot y una solución de copias de seguridad. Con eso ya tendrás cubiertos algunos de los problemas más habituales de cualquier web.<br />
<br />
¿Usas alguna otra que no esté en la lista? Compártela respondiendo en este tema.</span>]]></description>
			<content:encoded><![CDATA[<span style="font-size: x-large;" class="mycode_size"><span style="color: #2980b9;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">77 herramientas gratuitas para administradores web (SEO, VPS y seguridad)</span></span></span><br />
<br />
<br />
<span style="font-size: large;" class="mycode_size">Administrar una web moderna implica vigilar la seguridad, el rendimiento, el SEO, las copias de seguridad, el correo, los DNS y muchas otras tareas a la vez. Tanto si administras un foro, un blog, una tienda online, un VPS, o trabajas como webmaster o administrador de sistemas, existen herramientas gratuitas que ayudan a detectar problemas, automatizar tareas y ahorrar dinero en hosting — muchas de ellas pueden utilizarse sin experiencia avanzada.<br />
<br />
En esta guía encontrarás 77 herramientas gratuitas organizadas por categorías, numeradas consecutivamente del 1 al 77 para facilitar su consulta. La mayoría de administradores solo utilizarán entre 5 y 15 de esta lista de forma habitual — el resto quedan aquí para cuando te surja esa necesidad concreta.</span><br />
 <br />
<hr class="mycode_hr" />
<br />
<span style="font-size: x-large;" class="mycode_size"><span style="color: #2980b9;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">Resumen: qué herramienta según tu necesidad</span></span></span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">SEO</span> → Google Search Console</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Velocidad</span> → GTmetrix</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Seguridad</span> → VirusTotal</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Monitorización</span> → UptimeRobot</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Correo</span> → Mail-Tester</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">DNS</span> → Cloudflare</span><br />
</li>
</ul>
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Si administras un foro con Risus Nova</span>, estas son las que más te van a servir de toda la lista:</span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size">Cloudflare Turnstile — corta bots de registro sin molestar a usuarios reales.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Google Search Console — para saber si Google indexa bien tus posts y comunidades.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Cloudflare — protección y velocidad, sin tocar tu hosting.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">UptimeRobot — te avisa si el foro se cae.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Mail-Tester — para que las notificaciones y verificaciones de registro no acaben en spam.</span><br />
</li>
</ul>
 <br />
<hr class="mycode_hr" />
<br />
<span style="font-size: x-large;" class="mycode_size"><span style="color: #2980b9;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">Índice</span></span></span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size">Seguridad</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Rendimiento y velocidad</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Monitorización y uptime</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">SEO</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Correo electrónico</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Optimización de imágenes</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Backups y automatización</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Gestión de servidor y archivos</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Bases de datos</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Linux y VPS</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Testing y desarrollo</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">DNS y dominios</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">IA para administradores web</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Productividad</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Otros útiles</span><br />
</li>
</ul>
 <br />
<hr class="mycode_hr" />
<br />
<span style="font-size: x-large;" class="mycode_size"><span style="color: #2980b9;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">¿Qué problema tienes ahora mismo?</span></span></span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Mi web va lenta</span> → GTmetrix, PageSpeed Insights, WebPageTest.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">No sé si Google indexa bien mi web</span> → Google Search Console.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Mi correo no llega o cae en spam</span> → Mail-Tester, MXToolbox.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Tengo miedo de malware o phishing</span> → VirusTotal, Sucuri SiteCheck.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Mi web se cae y no me entero</span> → UptimeRobot, StatusCake.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">No sé si mi SSL está bien configurado</span> → Qualys SSL Labs.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Quiero hacer copias de seguridad automáticas</span> → UpdraftPlus, Cron-job.org.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Administro un VPS y quiero vigilarlo mejor</span> → htop, fail2ban, Webmin.</span><br />
</li>
</ul>
 <br />
<hr class="mycode_hr" />
<br />
<span style="font-size: x-large;" class="mycode_size"><span style="color: #2980b9;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">Si solo pudiera recomendar 10, serían estas</span></span></span><br />
<ol type="1" class="mycode_list"><li><span style="font-size: large;" class="mycode_size">Google Search Console</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Cloudflare</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">UptimeRobot</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">VirusTotal</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">GTmetrix</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">FileZilla</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">MXToolbox</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">TinyPNG</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Qualys SSL Labs</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">ChatGPT</span><br />
</li>
</ol>
<br />
<span style="font-size: large;" class="mycode_size">Si eres nuevo administrando una web, empieza por estas diez y no te compliques con el resto hasta que realmente las necesites.<br />
<br />
Con estas 10 ya cubres seguridad básica, velocidad, SEO, correo y monitorización. El resto de la lista son herramientas para necesidades más concretas.</span><br />
<br />
<br />
<span style="font-size: x-large;" class="mycode_size"><span style="color: #2980b9;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">Recomendaciones según tu proyecto</span></span></span><br />
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Si tienes un blog:</span></span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size">Google Search Console</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Google Analytics</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Cloudflare</span><br />
</li>
</ul>
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Si tienes un foro o comunidad:</span></span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size">UptimeRobot</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Cloudflare</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">MXToolbox</span><br />
</li>
</ul>
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Si administras un VPS:</span></span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size">htop</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">fail2ban</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Webmin</span><br />
</li>
</ul>
 <br />
<hr class="mycode_hr" />
<br />
<span style="font-size: x-large;" class="mycode_size"><span style="color: #2980b9;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">Seguridad</span></span></span><br />
<ol type="1" class="mycode_list"><li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">VirusTotal</span> ⭐⭐⭐⭐⭐ — analiza archivos y URLs con decenas de motores antivirus a la vez, útil para comprobar un enlace sospechoso o un archivo antes de subirlo a tu servidor.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Sucuri SiteCheck</span> ⭐⭐⭐⭐ — escanea tu web en busca de malware, listas negras y código inyectado, sin instalar nada.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Qualys SSL Labs (SSL Test)</span> ⭐⭐⭐⭐⭐ — analiza la configuración SSL/TLS de tu dominio y te da una nota de la A a la F, con el detalle de qué falla.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Let's Encrypt</span> ⭐⭐⭐⭐ — certificados SSL gratuitos con renovación automática, el estándar actual para tener HTTPS sin coste.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Have I Been Pwned</span> ⭐⭐⭐⭐ — comprueba si un email tuyo o de tus usuarios ha aparecido en alguna filtración de datos conocida.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">OWASP ZAP</span> ⭐⭐⭐ — escáner de vulnerabilidades web de código abierto, más orientado a quien quiera auditar su propia web a fondo.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">SecurityHeaders</span> ⭐⭐⭐⭐ — analiza las cabeceras de seguridad HTTP de tu web (CSP, HSTS, etc.) y te dice qué te falta.</span><br />
</li>
</ol>
<br />
<span style="font-size: x-large;" class="mycode_size"><span style="color: #2980b9;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">Rendimiento y velocidad</span></span></span><br />
<ol type="1" class="mycode_list"><li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Google PageSpeed Insights</span> ⭐⭐⭐⭐ — mide la velocidad de carga en móvil y escritorio, con recomendaciones concretas priorizadas por impacto.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">GTmetrix</span> ⭐⭐⭐⭐ — desglosa exactamente qué recursos frenan tu web (imágenes, scripts, servidor lento...).</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">WebPageTest</span> ⭐⭐⭐ — pruebas de velocidad desde ubicaciones y navegadores reales de todo el mundo, más técnico que los anteriores.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Chrome DevTools (Lighthouse)</span> ⭐⭐⭐⭐ — auditoría de rendimiento, accesibilidad y SEO integrada directamente en el navegador, sin salir de él.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Pingdom Website Speed Test</span> ⭐⭐⭐ — prueba de velocidad rápida y sencilla, buena como segunda opinión.</span><br />
</li>
</ol>
<br />
<span style="font-size: x-large;" class="mycode_size"><span style="color: #2980b9;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">Monitorización y uptime</span></span></span><br />
<ol type="1" class="mycode_list"><li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">UptimeRobot</span> ⭐⭐⭐⭐⭐ — te avisa por email/SMS si tu web se cae, gratis hasta 50 monitores cada 5 minutos.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">StatusCake</span> ⭐⭐⭐⭐ — alternativa a UptimeRobot, con plan gratuito permanente y buenas alertas.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Freshping</span> ⭐⭐⭐ — monitorización gratuita de Freshworks, sencilla de configurar.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Cronitor</span> ⭐⭐⭐ — pensada específicamente para vigilar que tus tareas cron se ejecuten a tiempo, no solo si la web está caída.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Netdata</span> ⭐⭐⭐⭐ — monitorización en tiempo real de CPU, memoria y disco de tu servidor, con panel visual muy detallado, gratis para un solo nodo.</span><br />
</li>
</ol>
<br />
<span style="font-size: x-large;" class="mycode_size"><span style="color: #2980b9;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">SEO</span></span></span><br />
<ol type="1" class="mycode_list"><li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Google Search Console</span> ⭐⭐⭐⭐⭐ — imprescindible: te muestra exactamente cómo ve Google tu sitio, qué páginas indexa y qué errores encuentra.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Google Analytics</span> ⭐⭐⭐⭐ — estadísticas reales de visitas y comportamiento de usuarios, la referencia del sector.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Bing Webmaster Tools</span> ⭐⭐⭐ — lo mismo que Search Console pero para Bing, menos tráfico pero se configura en 5 minutos.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Screaming Frog SEO Spider</span> ⭐⭐⭐⭐ — rastrea tu web como lo haría un buscador, gratis hasta 500 URLs, ideal para encontrar enlaces rotos o títulos duplicados.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Ubersuggest</span> ⭐⭐⭐ — ideas de palabras clave, versión gratuita con búsquedas diarias limitadas.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">AnswerThePublic</span> ⭐⭐⭐ — muestra preguntas reales que la gente busca sobre un tema, útil para elegir de qué escribir.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Google Trends</span> ⭐⭐⭐⭐ — descubre tendencias de búsqueda y compara el interés entre distintos temas a lo largo del tiempo.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Matomo</span> ⭐⭐⭐⭐ — alternativa a Google Analytics que respeta más la privacidad de tus usuarios, puedes alojarla tú mismo.</span><br />
</li>
</ol>
<br />
<span style="font-size: x-large;" class="mycode_size"><span style="color: #2980b9;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">Correo electrónico</span></span></span><br />
<ol type="1" class="mycode_list"><li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Mail-Tester</span> ⭐⭐⭐⭐⭐ — te da una puntuación sobre 10 de si tus correos van a llegar a la bandeja de entrada o a spam, y por qué.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">MXToolbox</span> ⭐⭐⭐⭐ — comprobación de registros MX, si tu dominio está en alguna lista negra de spam, y mucho más.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">SPF Record Generator</span> ⭐⭐⭐⭐ — genera el registro SPF correcto para que tu dominio no sea usado para suplantar correos.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">DMARC Analyzer</span> ⭐⭐⭐ — analiza tu configuración DMARC, el último paso para tener el correo de tu dominio bien protegido.</span><br />
</li>
</ol>
<br />
<span style="font-size: x-large;" class="mycode_size"><span style="color: #2980b9;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">Optimización de imágenes</span></span></span><br />
<ol type="1" class="mycode_list"><li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">TinyPNG</span> ⭐⭐⭐⭐⭐ — comprime PNG/JPG sin pérdida visible de calidad, en segundos.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Squoosh</span> ⭐⭐⭐⭐ — compresor de imágenes de Google, funciona todo en el navegador sin subir nada a ningún servidor.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Compressor.io</span> ⭐⭐⭐ — otra alternativa online de compresión, con más control manual sobre la calidad.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">ImageOptim</span> (Mac) ⭐⭐⭐⭐ — optimización de imágenes nativa y automática para quien trabaje en macOS.</span><br />
</li>
</ol>
<br />
<span style="font-size: x-large;" class="mycode_size"><span style="color: #2980b9;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">Backups y automatización</span></span></span><br />
<ol type="1" class="mycode_list"><li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">UpdraftPlus</span> ⭐⭐⭐⭐ — copias de seguridad automáticas con la versión gratuita más completa del mercado.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Cron-job.org</span> ⭐⭐⭐⭐ — programador de tareas cron gratuito en la nube, útil si tu hosting no te deja configurarlas cómodamente.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">rclone</span> ⭐⭐⭐ — sincroniza tus backups automáticamente con Google Drive, Dropbox y similares.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Rsync</span> ⭐⭐⭐ — la herramienta clásica de sincronización/backups en Linux, para quien maneje terminal.</span><br />
</li>
</ol>
<br />
<span style="font-size: x-large;" class="mycode_size"><span style="color: #2980b9;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">Gestión de servidor y archivos</span></span></span><br />
<ol type="1" class="mycode_list"><li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">phpMyAdmin</span> ⭐⭐⭐⭐ — gestión visual de bases de datos MySQL, viene preinstalado en la mayoría de hostings.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Adminer</span> ⭐⭐⭐⭐ — alternativa ligera a phpMyAdmin, cabe en un solo archivo PHP, ideal si tu hosting no lo trae.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Webmin</span> ⭐⭐⭐ — panel de administración completo para servidores Linux, para quien tenga un VPS.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">FileZilla</span> ⭐⭐⭐⭐ — cliente FTP/SFTP gratuito y multiplataforma, el más usado del sector.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">WinSCP</span> ⭐⭐⭐⭐ — cliente SFTP/SCP para Windows, alternativa a FileZilla.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">htop</span> ⭐⭐⭐ — monitor de procesos en Linux, mucho más visual que el clásico `top`.</span><br />
</li>
</ol>
<br />
<span style="font-size: x-large;" class="mycode_size"><span style="color: #2980b9;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">Bases de datos</span></span></span><br />
<ol type="1" class="mycode_list"><li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">DBeaver</span> ⭐⭐⭐⭐ — gestor visual de bases de datos multiplataforma, más potente que phpMyAdmin para trabajo avanzado.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">HeidiSQL</span> ⭐⭐⭐⭐ — cliente MySQL ligero y gratuito para Windows, muy usado por su sencillez.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">MySQL Workbench</span> ⭐⭐⭐ — herramienta oficial de MySQL, incluye diseño visual de bases de datos además de gestión.</span><br />
</li>
</ol>
<br />
<span style="font-size: x-large;" class="mycode_size"><span style="color: #2980b9;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">Linux y VPS</span></span></span><br />
<ol type="1" class="mycode_list"><li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">fail2ban</span> ⭐⭐⭐⭐⭐ — bloquea automáticamente IPs que intentan acceder por fuerza bruta (SSH, login, etc.).</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">btop</span> ⭐⭐⭐⭐ — monitor de recursos del sistema con una interfaz visual moderna, evolución de htop.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">tmux</span> ⭐⭐⭐ — permite mantener sesiones de terminal abiertas aunque se corte la conexión SSH.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">ncdu</span> ⭐⭐⭐⭐ — te muestra visualmente qué carpetas ocupan más espacio en tu servidor, ideal cuando se llena el disco.</span><br />
</li>
</ol>
<br />
<span style="font-size: x-large;" class="mycode_size"><span style="color: #2980b9;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">Testing y desarrollo</span></span></span><br />
<ol type="1" class="mycode_list"><li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Postman</span> ⭐⭐⭐⭐ — pruebas de APIs con plan gratuito muy completo, estándar en el sector.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">ngrok</span> ⭐⭐⭐ — expone tu servidor local a internet temporalmente, útil para probar webhooks sin subir nada a producción.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">3v4l.org</span> ⭐⭐⭐⭐ — prueba un mismo código PHP en varias versiones a la vez, perfecto para comprobar compatibilidad antes de actualizar PHP.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Regex101</span> ⭐⭐⭐ — prueba expresiones regulares en tiempo real, con explicación de cada parte del patrón.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">JSONLint</span> ⭐⭐⭐ — valida y da formato a JSON cuando algo no carga y sospechas que el formato está mal.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">CyberChef</span> ⭐⭐⭐⭐ — "la navaja suiza" para codificar, decodificar, cifrar o transformar texto y datos, todo en el navegador.</span><br />
</li>
</ol>
<br />
<span style="font-size: x-large;" class="mycode_size"><span style="color: #2980b9;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">DNS y dominios</span></span></span><br />
<ol type="1" class="mycode_list"><li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">IntoDNS</span> ⭐⭐⭐⭐ — análisis completo de la salud de tu configuración DNS, detecta errores comunes de un vistazo.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">DNS Checker</span> ⭐⭐⭐⭐ — ver si un cambio de DNS ya se ha propagado globalmente, evita la duda de "¿por qué no veo el cambio todavía?".</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">WHOIS Lookup</span> ⭐⭐⭐ — información pública de registro de un dominio (cuándo caduca, quién lo gestiona).</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Cloudflare</span> (plan gratuito) ⭐⭐⭐⭐⭐ — DNS ultrarrápido, CDN global, protección contra ataques, caché y optimización de rendimiento, todo junto. Probablemente la mejora gratuita con más impacto que puede aplicar una web pequeña o mediana.</span><br />
</li>
</ol>
<br />
<span style="font-size: x-large;" class="mycode_size"><span style="color: #2980b9;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">Anti-spam y moderación (para foros y comunidades)</span></span></span><br />
<br />
<span style="font-size: large;" class="mycode_size">Si administras un foro como Risus Nova en vez de un blog, estas te van a servir más que muchas de las genéricas de la lista.</span><br />
<ol type="1" class="mycode_list"><li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Cloudflare Turnstile</span> ⭐⭐⭐⭐⭐ — alternativa gratuita a reCAPTCHA, no molesta al usuario con puzzles y detecta bots a nivel de red.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">reCAPTCHA (v3)</span> ⭐⭐⭐⭐ — el clásico de Google, analiza el comportamiento en vez de pedir un puzzle visible.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Akismet</span> ⭐⭐⭐⭐ — filtro anti-spam para comentarios/posts entrenado con datos de millones de sitios, gratis para uso personal.</span><br />
</li>
</ol>
<br />
<span style="font-size: x-large;" class="mycode_size"><span style="color: #2980b9;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">IA para administradores web</span></span></span><br />
<br />
<span style="font-size: large;" class="mycode_size">No para generar spam ni contenido automático de mala calidad, sino como apoyo real para documentación, soporte y análisis de código.</span><br />
<ol type="1" class="mycode_list"><li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">ChatGPT</span> ⭐⭐⭐⭐ — útil para depurar errores, generar documentación o explicar código que no es tuyo.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Claude</span> ⭐⭐⭐⭐ — buena opción para trabajar con archivos largos (CSS/JS completos) y para tareas de edición de código con contexto amplio.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Gemini</span> ⭐⭐⭐ — integrado con el ecosistema de Google, útil si ya usas Search Console/Analytics a diario.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Perplexity</span> ⭐⭐⭐ — más orientado a búsqueda con fuentes citadas, útil para investigar antes de tomar una decisión técnica.</span><br />
</li>
</ol>
<br />
<span style="font-size: x-large;" class="mycode_size"><span style="color: #2980b9;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">Productividad</span></span></span><br />
<br />
<span style="font-size: large;" class="mycode_size">Muchos administradores llevan su proyecto solos — estas ayudan a organizarse.</span><br />
<ol type="1" class="mycode_list"><li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Obsidian</span> ⭐⭐⭐⭐ — notas en texto plano enlazadas entre sí, muy usado para documentar procesos técnicos propios.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Notion</span> ⭐⭐⭐⭐ — organización de tareas, notas y documentación en un solo sitio, con plan gratuito generoso.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Trello</span> ⭐⭐⭐ — tableros tipo kanban para llevar el seguimiento de tareas pendientes del proyecto.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Joplin</span> ⭐⭐⭐ — alternativa de notas de código abierto, con cifrado y sincronización propia.</span><br />
</li>
</ol>
<br />
<span style="font-size: x-large;" class="mycode_size"><span style="color: #2980b9;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">Otros útiles</span></span></span><br />
<ol type="1" class="mycode_list"><li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">W3C Validator</span> ⭐⭐⭐ — comprueba que tu HTML/CSS cumple los estándares oficiales.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Can I Use</span> ⭐⭐⭐⭐ — compatibilidad de funciones web según el navegador, antes de usar algo muy nuevo en CSS/JS.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Diffchecker</span> ⭐⭐⭐⭐ — compara dos textos o archivos y resalta las diferencias línea por línea.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">TinyURL</span> ⭐⭐⭐ — acortador de enlaces gratuito y sencillo, sin necesidad de cuenta.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Wayback Machine</span> (archive.org) ⭐⭐⭐⭐ — consulta versiones antiguas de cualquier web, útil para recuperar contenido perdido.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Google Safe Browsing Transparency Report</span> ⭐⭐⭐⭐ — comprueba si un sitio (el tuyo u otro) está marcado como peligroso por Google.</span><br />
</li>
</ol>
 <br />
<hr class="mycode_hr" />
<br />
<span style="font-size: x-large;" class="mycode_size"><span style="color: #2980b9;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">Problemas habituales y herramienta recomendada</span></span></span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size">Mi web va lenta → GTmetrix</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Mis correos llegan a spam → Mail-Tester</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Google no indexa mis páginas → Search Console</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">No sé por qué mi servidor consume tanta RAM → htop</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Mi SSL da errores → SSL Labs</span><br />
</li>
</ul>
 <br />
<hr class="mycode_hr" />
<br />
<span style="font-size: x-large;" class="mycode_size"><span style="color: #c0392b;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">Errores comunes</span></span></span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size">❌ Instalar herramientas porque sí, sin tener un problema real que resolver.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">❌ Configurar Cloudflare sin entender antes cómo funciona tu DNS.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">❌ Ignorar Search Console durante meses sin revisar los errores que reporta.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">❌ No probar nunca si tus backups realmente se pueden restaurar.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">❌ No revisar las alertas de uptime hasta que ya llevas horas caído.</span><br />
</li>
</ul>
 <br />
<hr class="mycode_hr" />
<br />
<span style="font-size: x-large;" class="mycode_size"><span style="color: #2980b9;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">Preguntas frecuentes</span></span></span><br />
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">¿Cuál es la mejor herramienta SEO gratuita?</span><br />
Google Search Console, sin discusión — te dice exactamente cómo ve Google tu sitio.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">¿Qué herramienta gratuita sirve para saber si una web está caída?</span><br />
UptimeRobot, gratis hasta 50 monitores.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">¿Qué herramienta gratuita sirve para analizar SSL?</span><br />
Qualys SSL Labs.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">¿Cuál es la mejor herramienta para comprobar DNS?</span><br />
IntoDNS para un chequeo completo, o MXToolbox si el problema es específico del correo.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">¿Uso Cloudflare o solo cambio el hosting?</span><br />
Ambas cosas cumplen funciones distintas: Cloudflare protege y acelera tu web sin cambiar de hosting, es casi siempre la primera mejora que merece la pena hacer.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">¿Necesito usar todas estas herramientas?</span><br />
No. La mayoría de administradores utilizan menos de diez de forma habitual.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">¿Qué herramientas instalar primero en una web nueva?</span><br />
Search Console, Cloudflare, UptimeRobot y una solución de copias de seguridad.</span><br />
 <br />
<hr class="mycode_hr" />
<br />
<span style="font-size: x-large;" class="mycode_size"><span style="color: #2980b9;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">Tutoriales relacionados de Risus Nova</span></span></span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size">Cómo publicar un producto en el Catálogo de Ventas</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Cómo funcionan los Posts Conjuntos (coautoría)</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Autoguardado y recuperación de Borradores</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Cómo añadir una encuesta a tu post</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Error 500, 403 y 404 — diagnóstico rápido y soluciones</span><br />
</li>
</ul>
 <br />
<hr class="mycode_hr" />
<br />
<span style="font-size: x-large;" class="mycode_size"><span style="color: #27ae60;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">Conclusión</span></span></span><br />
<br />
<span style="font-size: large;" class="mycode_size">No necesitas utilizar las 77 herramientas. De hecho, la mayoría de administradores gestionan sus proyectos con menos de 10. Lo importante es conocer qué problema quieres resolver y saber qué herramienta puede ayudarte cuando llegue el momento.<br />
<br />
Si estás empezando, configura primero Search Console, Cloudflare, UptimeRobot y una solución de copias de seguridad. Con eso ya tendrás cubiertos algunos de los problemas más habituales de cualquier web.<br />
<br />
¿Usas alguna otra que no esté en la lista? Compártela respondiendo en este tema.</span>]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[Error 500, 403 y 404: diagnóstico rápido, causas y soluciones]]></title>
			<link>https://phpost.es/tema-Tutorial-Error-500-403-y-404-diagn%C3%B3stico-r%C3%A1pido-causas-y-soluciones</link>
			<pubDate>Sun, 05 Jul 2026 18:58:08 +0200</pubDate>
			<dc:creator><![CDATA[<a href="https://phpost.es/member.php?action=profile&uid=1">Tronlar</a>]]></dc:creator>
			<guid isPermaLink="false">https://phpost.es/tema-Tutorial-Error-500-403-y-404-diagn%C3%B3stico-r%C3%A1pido-causas-y-soluciones</guid>
			<description><![CDATA[<span style="font-size: x-large;" class="mycode_size"><span style="color: #2980b9;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">Error 500, 403 y 404: diagnóstico rápido, causas y soluciones</span></span></span><br />
<br />
<span style="font-size: large;" class="mycode_size"><span style="color: #2980b9;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">Resumen rápido</span></span></span><ul class="mycode_list"><li><span style="font-weight: bold;" class="mycode_b">Error 500</span> (Error interno del servidor) → mira primero: logs de PHP y `.htaccess`.<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">Error 403</span> (Acceso prohibido) → mira primero: permisos y reglas de seguridad.<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">Error 404</span> (Página no encontrada) → mira primero: URL, `.htaccess` y `mod_rewrite`.<br />
</li>
</ul>
 <br />
<hr class="mycode_hr" />
<br />
<span style="font-size: x-large;" class="mycode_size"><span style="color: #2980b9;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">Árbol de diagnóstico rápido</span></span></span><br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>¿Ves Error 500?<br />
↓<br />
¿Has modificado .htaccess?<br />
↓<br />
Sí → Revísalo primero.<br />
No → Mira los logs.<br />
<br />
¿Ves Error 403?<br />
↓<br />
¿Has cambiado permisos?<br />
↓<br />
Sí → Revisa 755 y 644.<br />
<br />
¿Ves Error 404?<br />
↓<br />
¿Funcionan las URLs amigables?<br />
↓<br />
No → Revisa mod_rewrite y .htaccess.</code></div></div> <br />
<hr class="mycode_hr" />
<br />
<span style="font-size: x-large;" class="mycode_size"><span style="color: #2980b9;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">Error 500 (Internal Server Error)</span></span></span><br />
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Síntomas habituales:</span></span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size">Pantalla en blanco.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Mensaje "Internal Server Error".</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">La web deja de cargar justo tras instalar un complemento.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">La web deja de funcionar tras modificar el `.htaccess`.</span><br />
</li>
</ul>
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Causas más comunes:</span></span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size">Un `.htaccess` con una regla mal escrita o incompatible con tu servidor.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Permisos de archivos/carpetas incorrectos.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Un error fatal de PHP que tu hosting oculta por configuración.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Memoria insuficiente (`memory_limit` de PHP demasiado bajo).</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Versión de PHP incompatible con tu versión de Risus Nova o con algún complemento instalado.</span><br />
</li>
</ul>
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Cómo solucionarlo:</span></span><br />
<ol type="1" class="mycode_list"><li><span style="font-size: large;" class="mycode_size">Activa temporalmente la visualización de errores de PHP (`display_errors`) o consulta directamente los logs del servidor — recarga la página y verás el error real en vez del 500 genérico. Ten en cuenta que muchos hostings modernos bloquean `display_errors` por seguridad, así que si no funciona, ve directo a los logs.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Si no puedes activarlo, revisa el log de errores de tu hosting.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Renombra tu `.htaccess` a `.htaccess.bak` temporalmente. Si el error desaparece, el problema está ahí.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Sube el `.htaccess` original de Risus Nova y ve añadiendo tus cambios de uno en uno.</span><br />
</li>
</ol>
 <br />
<hr class="mycode_hr" />
<br />
<span style="font-size: x-large;" class="mycode_size"><span style="color: #2980b9;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">Error 403 (Forbidden)</span></span></span><br />
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Síntomas habituales:</span></span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size">Mensaje "Forbidden".</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Solo falla una carpeta concreta, el resto del sitio funciona.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">El administrador entra sin problema, pero los usuarios normales no.</span><br />
</li>
</ul>
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Causas más comunes:</span></span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size">Permisos de carpeta demasiado restrictivos, o al revés, demasiado abiertos (777, que muchos hostings bloquean directamente).</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Falta un `index.php` en una carpeta y el servidor no permite listar directorios.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Una regla en `.htaccess` bloqueando esa ruta.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Tu IP bloqueada por el firewall del hosting (a veces pasa tras varios intentos fallidos de login).</span><br />
</li>
</ul>
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Cómo solucionarlo:</span></span><br />
<ol type="1" class="mycode_list"><li><span style="font-size: large;" class="mycode_size">Permisos correctos: carpetas en `755`, archivos en `644`.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Comprueba que existe un `index.php` (aunque esté vacío) en carpetas que no deban listarse.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Revisa tu `.htaccess` por `Deny from` o `Require all denied` que no recuerdes haber puesto.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Si sospechas que es tu propia IP, contacta con tu hosting para que la desbloqueen.</span><br />
</li>
</ol>
 <br />
<hr class="mycode_hr" />
<br />
<span style="font-size: x-large;" class="mycode_size"><span style="color: #2980b9;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">Error 404 (Not Found)</span></span></span><br />
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Síntomas habituales:</span></span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size">La portada funciona, pero los temas/posts individuales no.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Las URLs amigables fallan.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Algunas páginas existen y dan error igualmente.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Error 404 tras activar URLs amigables.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Error 404 en temas y categorías.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Error 404 después de migrar el sitio.</span><br />
</li>
</ul>
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Causas más comunes:</span></span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size">Falta o está mal configurado el `.htaccess` de reescritura de URLs.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">El módulo `mod_rewrite` de Apache no está activado.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Moviste o renombraste un archivo/carpeta y algún enlace interno sigue apuntando a la ruta vieja.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Subiste los archivos a la carpeta equivocada (una subcarpeta extra sin darte cuenta).</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">La URL base configurada en Risus Nova no coincide con la ubicación real de la instalación (muy común al mover el foro de `/foro/` a la raíz `/`, o al revés).</span><br />
</li>
</ul>
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Cómo solucionarlo:</span></span><br />
<ol type="1" class="mycode_list"><li><span style="font-size: large;" class="mycode_size">Confirma con tu hosting que `mod_rewrite` está activo.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Verifica que el `.htaccess` de Risus Nova está en la raíz del sitio, no en una subcarpeta.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Por FTP, confirma que los archivos están directamente en `public_html` (o la raíz de tu dominio).</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Revisa en `Admin → Configuración` que la URL base esté bien escrita, sin barra final de más ni de menos.</span><br />
</li>
</ol>
 <br />
<hr class="mycode_hr" />
<br />
<span style="font-size: x-large;" class="mycode_size"><span style="color: #2980b9;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">El error apareció tras instalar un complemento</span></span></span><br />
<br />
<span style="font-size: large;" class="mycode_size">Si el problema empezó justo después de instalar o actualizar un complemento:</span><br />
<ol type="1" class="mycode_list"><li><span style="font-size: large;" class="mycode_size">Desactiva temporalmente el complemento.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Vacía la caché del navegador.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Comprueba los logs del servidor.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Prueba de nuevo con el complemento desactivado.</span><br />
</li>
</ol>
 <br />
<hr class="mycode_hr" />
<br />
<span style="font-size: x-large;" class="mycode_size"><span style="color: #2980b9;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">Dónde encontrar los registros de errores (logs)</span></span></span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size">cPanel → Métricas → Errores.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Plesk → Registros.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Hosting compartido sin cPanel/Plesk → consulta el panel de control específico de tu proveedor, suele tener una sección de "Registros" o "Logs de errores".</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">VPS con Apache → `/var/log/apache2/error.log`</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">VPS con Nginx → `/var/log/nginx/error.log`</span><br />
</li>
</ul>
 <br />
<hr class="mycode_hr" />
<br />
<span style="font-size: x-large;" class="mycode_size"><span style="color: #e74c3c;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">Antes de pedir ayuda en el foro, indica:</span></span></span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size">Versión de Risus Nova.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Versión de PHP.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Hosting utilizado.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Qué cambio hiciste justo antes de que empezara el error.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Captura de pantalla o el mensaje de error exacto.</span><br />
</li>
</ul>
<br />
<span style="font-size: large;" class="mycode_size">Con estos datos, cualquiera que te ayude en el foro podrá diagnosticarlo mucho más rápido.</span><br />
 <br />
<hr class="mycode_hr" />
<br />
<span style="font-size: x-large;" class="mycode_size"><span style="color: #27ae60;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">Conclusión</span></span></span><br />
<br />
<span style="font-size: large;" class="mycode_size">La mayoría de errores 500, 403 y 404 se deben a permisos incorrectos, configuraciones erróneas en `.htaccess` o problemas de compatibilidad con PHP.<br />
<br />
Si revisas los logs del servidor y sigues los pasos de esta guía, normalmente podrás localizar el origen del problema en pocos minutos.</span>]]></description>
			<content:encoded><![CDATA[<span style="font-size: x-large;" class="mycode_size"><span style="color: #2980b9;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">Error 500, 403 y 404: diagnóstico rápido, causas y soluciones</span></span></span><br />
<br />
<span style="font-size: large;" class="mycode_size"><span style="color: #2980b9;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">Resumen rápido</span></span></span><ul class="mycode_list"><li><span style="font-weight: bold;" class="mycode_b">Error 500</span> (Error interno del servidor) → mira primero: logs de PHP y `.htaccess`.<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">Error 403</span> (Acceso prohibido) → mira primero: permisos y reglas de seguridad.<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">Error 404</span> (Página no encontrada) → mira primero: URL, `.htaccess` y `mod_rewrite`.<br />
</li>
</ul>
 <br />
<hr class="mycode_hr" />
<br />
<span style="font-size: x-large;" class="mycode_size"><span style="color: #2980b9;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">Árbol de diagnóstico rápido</span></span></span><br />
<div class="codeblock"><div class="title">Código:</div><div class="body" dir="ltr"><code>¿Ves Error 500?<br />
↓<br />
¿Has modificado .htaccess?<br />
↓<br />
Sí → Revísalo primero.<br />
No → Mira los logs.<br />
<br />
¿Ves Error 403?<br />
↓<br />
¿Has cambiado permisos?<br />
↓<br />
Sí → Revisa 755 y 644.<br />
<br />
¿Ves Error 404?<br />
↓<br />
¿Funcionan las URLs amigables?<br />
↓<br />
No → Revisa mod_rewrite y .htaccess.</code></div></div> <br />
<hr class="mycode_hr" />
<br />
<span style="font-size: x-large;" class="mycode_size"><span style="color: #2980b9;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">Error 500 (Internal Server Error)</span></span></span><br />
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Síntomas habituales:</span></span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size">Pantalla en blanco.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Mensaje "Internal Server Error".</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">La web deja de cargar justo tras instalar un complemento.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">La web deja de funcionar tras modificar el `.htaccess`.</span><br />
</li>
</ul>
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Causas más comunes:</span></span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size">Un `.htaccess` con una regla mal escrita o incompatible con tu servidor.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Permisos de archivos/carpetas incorrectos.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Un error fatal de PHP que tu hosting oculta por configuración.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Memoria insuficiente (`memory_limit` de PHP demasiado bajo).</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Versión de PHP incompatible con tu versión de Risus Nova o con algún complemento instalado.</span><br />
</li>
</ul>
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Cómo solucionarlo:</span></span><br />
<ol type="1" class="mycode_list"><li><span style="font-size: large;" class="mycode_size">Activa temporalmente la visualización de errores de PHP (`display_errors`) o consulta directamente los logs del servidor — recarga la página y verás el error real en vez del 500 genérico. Ten en cuenta que muchos hostings modernos bloquean `display_errors` por seguridad, así que si no funciona, ve directo a los logs.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Si no puedes activarlo, revisa el log de errores de tu hosting.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Renombra tu `.htaccess` a `.htaccess.bak` temporalmente. Si el error desaparece, el problema está ahí.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Sube el `.htaccess` original de Risus Nova y ve añadiendo tus cambios de uno en uno.</span><br />
</li>
</ol>
 <br />
<hr class="mycode_hr" />
<br />
<span style="font-size: x-large;" class="mycode_size"><span style="color: #2980b9;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">Error 403 (Forbidden)</span></span></span><br />
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Síntomas habituales:</span></span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size">Mensaje "Forbidden".</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Solo falla una carpeta concreta, el resto del sitio funciona.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">El administrador entra sin problema, pero los usuarios normales no.</span><br />
</li>
</ul>
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Causas más comunes:</span></span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size">Permisos de carpeta demasiado restrictivos, o al revés, demasiado abiertos (777, que muchos hostings bloquean directamente).</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Falta un `index.php` en una carpeta y el servidor no permite listar directorios.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Una regla en `.htaccess` bloqueando esa ruta.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Tu IP bloqueada por el firewall del hosting (a veces pasa tras varios intentos fallidos de login).</span><br />
</li>
</ul>
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Cómo solucionarlo:</span></span><br />
<ol type="1" class="mycode_list"><li><span style="font-size: large;" class="mycode_size">Permisos correctos: carpetas en `755`, archivos en `644`.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Comprueba que existe un `index.php` (aunque esté vacío) en carpetas que no deban listarse.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Revisa tu `.htaccess` por `Deny from` o `Require all denied` que no recuerdes haber puesto.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Si sospechas que es tu propia IP, contacta con tu hosting para que la desbloqueen.</span><br />
</li>
</ol>
 <br />
<hr class="mycode_hr" />
<br />
<span style="font-size: x-large;" class="mycode_size"><span style="color: #2980b9;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">Error 404 (Not Found)</span></span></span><br />
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Síntomas habituales:</span></span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size">La portada funciona, pero los temas/posts individuales no.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Las URLs amigables fallan.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Algunas páginas existen y dan error igualmente.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Error 404 tras activar URLs amigables.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Error 404 en temas y categorías.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Error 404 después de migrar el sitio.</span><br />
</li>
</ul>
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Causas más comunes:</span></span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size">Falta o está mal configurado el `.htaccess` de reescritura de URLs.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">El módulo `mod_rewrite` de Apache no está activado.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Moviste o renombraste un archivo/carpeta y algún enlace interno sigue apuntando a la ruta vieja.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Subiste los archivos a la carpeta equivocada (una subcarpeta extra sin darte cuenta).</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">La URL base configurada en Risus Nova no coincide con la ubicación real de la instalación (muy común al mover el foro de `/foro/` a la raíz `/`, o al revés).</span><br />
</li>
</ul>
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Cómo solucionarlo:</span></span><br />
<ol type="1" class="mycode_list"><li><span style="font-size: large;" class="mycode_size">Confirma con tu hosting que `mod_rewrite` está activo.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Verifica que el `.htaccess` de Risus Nova está en la raíz del sitio, no en una subcarpeta.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Por FTP, confirma que los archivos están directamente en `public_html` (o la raíz de tu dominio).</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Revisa en `Admin → Configuración` que la URL base esté bien escrita, sin barra final de más ni de menos.</span><br />
</li>
</ol>
 <br />
<hr class="mycode_hr" />
<br />
<span style="font-size: x-large;" class="mycode_size"><span style="color: #2980b9;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">El error apareció tras instalar un complemento</span></span></span><br />
<br />
<span style="font-size: large;" class="mycode_size">Si el problema empezó justo después de instalar o actualizar un complemento:</span><br />
<ol type="1" class="mycode_list"><li><span style="font-size: large;" class="mycode_size">Desactiva temporalmente el complemento.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Vacía la caché del navegador.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Comprueba los logs del servidor.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Prueba de nuevo con el complemento desactivado.</span><br />
</li>
</ol>
 <br />
<hr class="mycode_hr" />
<br />
<span style="font-size: x-large;" class="mycode_size"><span style="color: #2980b9;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">Dónde encontrar los registros de errores (logs)</span></span></span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size">cPanel → Métricas → Errores.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Plesk → Registros.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Hosting compartido sin cPanel/Plesk → consulta el panel de control específico de tu proveedor, suele tener una sección de "Registros" o "Logs de errores".</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">VPS con Apache → `/var/log/apache2/error.log`</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">VPS con Nginx → `/var/log/nginx/error.log`</span><br />
</li>
</ul>
 <br />
<hr class="mycode_hr" />
<br />
<span style="font-size: x-large;" class="mycode_size"><span style="color: #e74c3c;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">Antes de pedir ayuda en el foro, indica:</span></span></span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size">Versión de Risus Nova.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Versión de PHP.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Hosting utilizado.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Qué cambio hiciste justo antes de que empezara el error.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Captura de pantalla o el mensaje de error exacto.</span><br />
</li>
</ul>
<br />
<span style="font-size: large;" class="mycode_size">Con estos datos, cualquiera que te ayude en el foro podrá diagnosticarlo mucho más rápido.</span><br />
 <br />
<hr class="mycode_hr" />
<br />
<span style="font-size: x-large;" class="mycode_size"><span style="color: #27ae60;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">Conclusión</span></span></span><br />
<br />
<span style="font-size: large;" class="mycode_size">La mayoría de errores 500, 403 y 404 se deben a permisos incorrectos, configuraciones erróneas en `.htaccess` o problemas de compatibilidad con PHP.<br />
<br />
Si revisas los logs del servidor y sigues los pasos de esta guía, normalmente podrás localizar el origen del problema en pocos minutos.</span>]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[Cómo funcionan los Posts Conjuntos (coautoría)]]></title>
			<link>https://phpost.es/tema-Tutorial-C%C3%B3mo-funcionan-los-Posts-Conjuntos-coautor%C3%ADa</link>
			<pubDate>Sun, 05 Jul 2026 00:31:23 +0200</pubDate>
			<dc:creator><![CDATA[<a href="https://phpost.es/member.php?action=profile&uid=1">Tronlar</a>]]></dc:creator>
			<guid isPermaLink="false">https://phpost.es/tema-Tutorial-C%C3%B3mo-funcionan-los-Posts-Conjuntos-coautor%C3%ADa</guid>
			<description><![CDATA[<span style="font-size: x-large;" class="mycode_size"><span style="color: #2980b9;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">Cómo funcionan los Posts Conjuntos (coautoría)</span></span></span><br />
<br />
<span style="font-size: large;" class="mycode_size">Los <span style="font-weight: bold;" class="mycode_b">Posts Conjuntos</span> te permiten compartir la autoría de un post con otro usuario. Ideal para colaboraciones: traducciones a cuatro manos, recopilaciones hechas entre dos, o cualquier contenido que hayáis trabajado juntos.</span><br />
<br />
<span style="font-size: large;" class="mycode_size"><span style="color: #2980b9;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">Invitar a un coautor</span></span></span><br />
 <br />
<ol type="1" class="mycode_list"><li><span style="font-size: large;" class="mycode_size">Al crear o editar un post, verás un campo para <span style="font-weight: bold;" class="mycode_b">buscar coautor</span>.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Empieza a escribir el nombre de usuario: el buscador te irá sugiriendo coincidencias en vivo, a medida que escribes.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Selecciona al usuario que quieres invitar y guarda el post.</span><br />
</li>
</ol>
<br />
<span style="font-size: large;" class="mycode_size">La invitación queda <span style="font-weight: bold;" class="mycode_b">pendiente</span> en ese momento. Todavía no es coautor de nada.<br />
<br />
<span style="color: #2980b9;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">Aceptar o rechazar una invitación</span></span></span><br />
<br />
<span style="font-size: large;" class="mycode_size">Si te invitan a ti como coautor de un post, verás la invitación directamente en la <span style="font-weight: bold;" class="mycode_b">página del post</span>, en la zona del autor. Desde ahí tienes dos botones:</span><br />
 <ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Aceptar</span>: pasas a ser coautor oficial del post.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Rechazar</span>: la invitación desaparece y el post sigue solo a nombre del autor original.</span><br />
</li>
</ul>
<br />
<span style="font-size: large;" class="mycode_size">Nadie queda como coautor sin haber confirmado la invitación primero — no es automático.</span><br />
<br />
<br />
<span style="font-size: large;" class="mycode_size"><span style="color: #2980b9;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">Reparto de puntos</span></span><br />
<br />
Una vez aceptada la invitación, los puntos que genere el post (votos, comentarios, etc., según cómo tengas configurado el sistema de puntos) se reparten <span style="font-weight: bold;" class="mycode_b">50/50</span> entre el autor original y el coautor.</span><br />
<br />
<br />
<span style="font-size: large;" class="mycode_size"><span style="color: #2980b9;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">Salir de la coautoría</span></span></span><br />
<br />
<span style="font-size: large;" class="mycode_size">Si eres coautor de un post y ya no quieres seguir siéndolo, puedes salir de la coautoría desde la misma página del post. Al salir, dejas de figurar como coautor y de recibir el reparto de puntos de ese post a partir de ese momento.</span><br />
<br />
<br />
<span style="font-size: large;" class="mycode_size"><span style="color: #e74c3c;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">Notas importantes</span></span></span><br />
 <ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size">Solo puede haber <span style="font-weight: bold;" class="mycode_b">un coautor</span> por post (no es un sistema de múltiples coautores).</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">La invitación no se puede forzar: si el invitado no acepta, sigue apareciendo como pendiente hasta que responda.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">El reparto de puntos aplica desde el momento de la aceptación, no de forma retroactiva.</span><br />
</li>
</ul>
<br />
<br />
<span style="font-size: large;" class="mycode_size">¿Dudas sobre cómo invitar o aceptar una coautoría? Responde en este mismo tema.</span>]]></description>
			<content:encoded><![CDATA[<span style="font-size: x-large;" class="mycode_size"><span style="color: #2980b9;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">Cómo funcionan los Posts Conjuntos (coautoría)</span></span></span><br />
<br />
<span style="font-size: large;" class="mycode_size">Los <span style="font-weight: bold;" class="mycode_b">Posts Conjuntos</span> te permiten compartir la autoría de un post con otro usuario. Ideal para colaboraciones: traducciones a cuatro manos, recopilaciones hechas entre dos, o cualquier contenido que hayáis trabajado juntos.</span><br />
<br />
<span style="font-size: large;" class="mycode_size"><span style="color: #2980b9;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">Invitar a un coautor</span></span></span><br />
 <br />
<ol type="1" class="mycode_list"><li><span style="font-size: large;" class="mycode_size">Al crear o editar un post, verás un campo para <span style="font-weight: bold;" class="mycode_b">buscar coautor</span>.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Empieza a escribir el nombre de usuario: el buscador te irá sugiriendo coincidencias en vivo, a medida que escribes.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Selecciona al usuario que quieres invitar y guarda el post.</span><br />
</li>
</ol>
<br />
<span style="font-size: large;" class="mycode_size">La invitación queda <span style="font-weight: bold;" class="mycode_b">pendiente</span> en ese momento. Todavía no es coautor de nada.<br />
<br />
<span style="color: #2980b9;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">Aceptar o rechazar una invitación</span></span></span><br />
<br />
<span style="font-size: large;" class="mycode_size">Si te invitan a ti como coautor de un post, verás la invitación directamente en la <span style="font-weight: bold;" class="mycode_b">página del post</span>, en la zona del autor. Desde ahí tienes dos botones:</span><br />
 <ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Aceptar</span>: pasas a ser coautor oficial del post.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Rechazar</span>: la invitación desaparece y el post sigue solo a nombre del autor original.</span><br />
</li>
</ul>
<br />
<span style="font-size: large;" class="mycode_size">Nadie queda como coautor sin haber confirmado la invitación primero — no es automático.</span><br />
<br />
<br />
<span style="font-size: large;" class="mycode_size"><span style="color: #2980b9;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">Reparto de puntos</span></span><br />
<br />
Una vez aceptada la invitación, los puntos que genere el post (votos, comentarios, etc., según cómo tengas configurado el sistema de puntos) se reparten <span style="font-weight: bold;" class="mycode_b">50/50</span> entre el autor original y el coautor.</span><br />
<br />
<br />
<span style="font-size: large;" class="mycode_size"><span style="color: #2980b9;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">Salir de la coautoría</span></span></span><br />
<br />
<span style="font-size: large;" class="mycode_size">Si eres coautor de un post y ya no quieres seguir siéndolo, puedes salir de la coautoría desde la misma página del post. Al salir, dejas de figurar como coautor y de recibir el reparto de puntos de ese post a partir de ese momento.</span><br />
<br />
<br />
<span style="font-size: large;" class="mycode_size"><span style="color: #e74c3c;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">Notas importantes</span></span></span><br />
 <ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size">Solo puede haber <span style="font-weight: bold;" class="mycode_b">un coautor</span> por post (no es un sistema de múltiples coautores).</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">La invitación no se puede forzar: si el invitado no acepta, sigue apareciendo como pendiente hasta que responda.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">El reparto de puntos aplica desde el momento de la aceptación, no de forma retroactiva.</span><br />
</li>
</ul>
<br />
<br />
<span style="font-size: large;" class="mycode_size">¿Dudas sobre cómo invitar o aceptar una coautoría? Responde en este mismo tema.</span>]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[Cómo usar el Catálogo de Ventas]]></title>
			<link>https://phpost.es/tema-Tutorial-C%C3%B3mo-usar-el-Cat%C3%A1logo-de-Ventas</link>
			<pubDate>Sun, 05 Jul 2026 00:28:39 +0200</pubDate>
			<dc:creator><![CDATA[<a href="https://phpost.es/member.php?action=profile&uid=1">Tronlar</a>]]></dc:creator>
			<guid isPermaLink="false">https://phpost.es/tema-Tutorial-C%C3%B3mo-usar-el-Cat%C3%A1logo-de-Ventas</guid>
			<description><![CDATA[<span style="font-size: x-large;" class="mycode_size"><span style="color: #2980b9;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">Cómo usar el Catálogo de Ventas</span></span></span><br />
<br />
<span style="font-size: large;" class="mycode_size">El <span style="font-weight: bold;" class="mycode_b">Catálogo de Ventas</span> es el marketplace interno de la comunidad. Cualquier usuario registrado puede publicar productos en venta y contactar con otros miembros de forma directa, sin salir del sitio.</span><br />
<br />
<span style="font-size: large;" class="mycode_size"><span style="color: #2980b9;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">¿Dónde está?</span></span></span><br />
<br />
<span style="font-size: large;" class="mycode_size">Se accede desde <span style="font-weight: bold;" class="mycode_b">/catalogo/</span>. Encontrarás el enlace en el menú principal del sitio, junto a Calendario, Chat y Sugerencias.</span><br />
<br />
<br />
<span style="font-size: large;" class="mycode_size"><span style="color: #2980b9;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">Publicar un producto</span></span></span><br />
 <br />
<ol type="1" class="mycode_list"><li><span style="font-size: large;" class="mycode_size">Entra a <span style="font-weight: bold;" class="mycode_b">/catalogo/</span> y pulsa en <span style="font-weight: bold;" class="mycode_b">Publicar producto</span>.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Rellena los datos:</span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Título</span> del producto.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Descripción</span> (puedes detallar estado, condiciones, forma de pago, etc.).</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Precio</span>.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Categoría</span> (elige la que mejor encaje con lo que vendes).</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Imagen</span> del producto (recomendado: sube una foto real, los anuncios con imagen se ven mucho más).</span><br />
</li>
</ul>
</li>
<li><span style="font-size: large;" class="mycode_size">Pulsa <span style="font-weight: bold;" class="mycode_b">Publicar</span>. Tu producto quedará visible en el catálogo para el resto de la comunidad.</span><br />
</li>
</ol>
<br />
<span style="font-size: large;" class="mycode_size"><span style="color: #2980b9;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">Buscar y ver productos</span></span></span><br />
<br />
<span style="font-size: large;" class="mycode_size">En el catálogo puedes:</span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size">Ver todos los productos publicados, ordenados por fecha.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Filtrar por categoría para encontrar más rápido lo que buscas.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Entrar a la ficha de cada producto para ver la descripción completa y la imagen en grande.</span><br />
</li>
</ul>
<br />
<span style="font-size: large;" class="mycode_size"><span style="color: #2980b9;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">Contactar con el vendedor</span></span></span><br />
<br />
<span style="font-size: large;" class="mycode_size">Si te interesa un producto, no hay un botón de "comprar" dentro del catálogo — el contacto se hace directamente por <span style="font-weight: bold;" class="mycode_b">mensaje privado</span> con el usuario que lo publicó. Desde la ficha del producto verás la opción para escribirle. Así, el precio, la forma de pago y el envío se acuerdan entre comprador y vendedor, igual que en cualquier marketplace de segunda mano.</span><br />
<br />
<br />
<span style="font-size: large;" class="mycode_size"><span style="color: #2980b9;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">Recomendaciones para vender mejor</span></span></span><br />
 <ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size">Usa un título claro y directo (qué es, y si es nuevo o usado).</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Sube al menos una foto real del producto.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Indica el precio desde el principio, evita anuncios sin precio ("a consultar"), suelen generar menos interés.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Responde rápido a los mensajes privados de gente interesada.</span><br />
</li>
</ul>
<br />
<span style="font-size: large;" class="mycode_size"><span style="color: #e74c3c;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">Notas importantes</span></span></span><br />
 <ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size">El Catálogo es un espacio de intercambio entre usuarios; la administración del sitio no interviene en las transacciones ni actúa como intermediaria de pago.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Usa el sentido común en cualquier intercambio con otro usuario: verifica antes de pagar por adelantado, y si algo no te da confianza, no sigas adelante.</span><br />
</li>
</ul>
<br />
<br />
<span style="font-size: large;" class="mycode_size">¿Dudas sobre cómo publicar o encontrar algo en el catálogo? Responde en este mismo tema.</span>]]></description>
			<content:encoded><![CDATA[<span style="font-size: x-large;" class="mycode_size"><span style="color: #2980b9;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">Cómo usar el Catálogo de Ventas</span></span></span><br />
<br />
<span style="font-size: large;" class="mycode_size">El <span style="font-weight: bold;" class="mycode_b">Catálogo de Ventas</span> es el marketplace interno de la comunidad. Cualquier usuario registrado puede publicar productos en venta y contactar con otros miembros de forma directa, sin salir del sitio.</span><br />
<br />
<span style="font-size: large;" class="mycode_size"><span style="color: #2980b9;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">¿Dónde está?</span></span></span><br />
<br />
<span style="font-size: large;" class="mycode_size">Se accede desde <span style="font-weight: bold;" class="mycode_b">/catalogo/</span>. Encontrarás el enlace en el menú principal del sitio, junto a Calendario, Chat y Sugerencias.</span><br />
<br />
<br />
<span style="font-size: large;" class="mycode_size"><span style="color: #2980b9;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">Publicar un producto</span></span></span><br />
 <br />
<ol type="1" class="mycode_list"><li><span style="font-size: large;" class="mycode_size">Entra a <span style="font-weight: bold;" class="mycode_b">/catalogo/</span> y pulsa en <span style="font-weight: bold;" class="mycode_b">Publicar producto</span>.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Rellena los datos:</span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Título</span> del producto.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Descripción</span> (puedes detallar estado, condiciones, forma de pago, etc.).</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Precio</span>.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Categoría</span> (elige la que mejor encaje con lo que vendes).</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Imagen</span> del producto (recomendado: sube una foto real, los anuncios con imagen se ven mucho más).</span><br />
</li>
</ul>
</li>
<li><span style="font-size: large;" class="mycode_size">Pulsa <span style="font-weight: bold;" class="mycode_b">Publicar</span>. Tu producto quedará visible en el catálogo para el resto de la comunidad.</span><br />
</li>
</ol>
<br />
<span style="font-size: large;" class="mycode_size"><span style="color: #2980b9;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">Buscar y ver productos</span></span></span><br />
<br />
<span style="font-size: large;" class="mycode_size">En el catálogo puedes:</span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size">Ver todos los productos publicados, ordenados por fecha.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Filtrar por categoría para encontrar más rápido lo que buscas.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Entrar a la ficha de cada producto para ver la descripción completa y la imagen en grande.</span><br />
</li>
</ul>
<br />
<span style="font-size: large;" class="mycode_size"><span style="color: #2980b9;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">Contactar con el vendedor</span></span></span><br />
<br />
<span style="font-size: large;" class="mycode_size">Si te interesa un producto, no hay un botón de "comprar" dentro del catálogo — el contacto se hace directamente por <span style="font-weight: bold;" class="mycode_b">mensaje privado</span> con el usuario que lo publicó. Desde la ficha del producto verás la opción para escribirle. Así, el precio, la forma de pago y el envío se acuerdan entre comprador y vendedor, igual que en cualquier marketplace de segunda mano.</span><br />
<br />
<br />
<span style="font-size: large;" class="mycode_size"><span style="color: #2980b9;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">Recomendaciones para vender mejor</span></span></span><br />
 <ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size">Usa un título claro y directo (qué es, y si es nuevo o usado).</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Sube al menos una foto real del producto.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Indica el precio desde el principio, evita anuncios sin precio ("a consultar"), suelen generar menos interés.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Responde rápido a los mensajes privados de gente interesada.</span><br />
</li>
</ul>
<br />
<span style="font-size: large;" class="mycode_size"><span style="color: #e74c3c;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">Notas importantes</span></span></span><br />
 <ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size">El Catálogo es un espacio de intercambio entre usuarios; la administración del sitio no interviene en las transacciones ni actúa como intermediaria de pago.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Usa el sentido común en cualquier intercambio con otro usuario: verifica antes de pagar por adelantado, y si algo no te da confianza, no sigas adelante.</span><br />
</li>
</ul>
<br />
<br />
<span style="font-size: large;" class="mycode_size">¿Dudas sobre cómo publicar o encontrar algo en el catálogo? Responde en este mismo tema.</span>]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[Las 20 Mejores Herramientas SEO Gratuitas en 2026]]></title>
			<link>https://phpost.es/tema-Tutorial-Las-20-Mejores-Herramientas-SEO-Gratuitas-en-2026</link>
			<pubDate>Sun, 28 Jun 2026 14:05:57 +0200</pubDate>
			<dc:creator><![CDATA[<a href="https://phpost.es/member.php?action=profile&uid=1">Tronlar</a>]]></dc:creator>
			<guid isPermaLink="false">https://phpost.es/tema-Tutorial-Las-20-Mejores-Herramientas-SEO-Gratuitas-en-2026</guid>
			<description><![CDATA[<div style="text-align: center;" class="mycode_align"><span style="color: #2980b9;" class="mycode_color"><span style="font-size: x-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Las 20 Mejores Herramientas SEO Gratuitas de 2026: Ventajas, Desventajas y Valoración</span></span></span></div>
<br />
<span style="font-size: large;" class="mycode_size">Si tienes una web, blog o tienda online, estas son las herramientas SEO gratuitas que más recomiendo. He seleccionado las más útiles para investigación de palabras clave, auditorías técnicas, velocidad web, backlinks y análisis de tráfico. Muchas de ellas son utilizadas diariamente por profesionales SEO de todo el mundo. </span><br />
 <br />
<hr class="mycode_hr" />
<br />
<span style="color: #2980b9;" class="mycode_color"><span style="font-size: x-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">1. Google Search Console</span></span></span><br />
<br />
<span style="color: #f39c12;" class="mycode_color"><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">¿Qué es?</span></span></span><br />
<br />
<span style="font-size: large;" class="mycode_size">La herramienta oficial de Google para analizar el rendimiento de una web en los resultados de búsqueda.</span><br />
<br />
<br />
<span style="color: #27ae60;" class="mycode_color"><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">✅ Lo bueno</span></span></span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size">Datos oficiales de Google.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Permite detectar errores de indexación.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Muestra clics, impresiones y posiciones.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Totalmente gratuita.</span><br />
</li>
</ul>
<br />
<span style="color: #e74c3c;" class="mycode_color"><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">❌ Lo malo</span></span></span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size">No muestra datos de la competencia.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Interfaz poco amigable para principiantes.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Información limitada comparada con herramientas premium.</span><br />
</li>
</ul>
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">⭐ Valoración:</span> 10/10</span><br />
 <br />
<hr class="mycode_hr" />
<br />
<span style="color: #2980b9;" class="mycode_color"><span style="font-size: x-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">2. Google Analytics 4</span></span></span><br />
<br />
<span style="color: #f39c12;" class="mycode_color"><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">¿Qué es?</span></span></span><br />
<br />
<span style="font-size: large;" class="mycode_size">La herramienta de analítica web más utilizada para medir visitas y comportamiento de usuarios.</span><br />
<br />
<br />
<span style="color: #27ae60;" class="mycode_color"><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">✅ Lo bueno</span></span></span><ul class="mycode_list"><li>Muy completa.<br />
</li>
<li>Integración perfecta con Google.<br />
</li>
<li>Permite medir conversiones.<br />
</li>
</ul>
<br />
<span style="color: #e74c3c;" class="mycode_color"><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">❌ Lo malo</span></span></span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size">Curva de aprendizaje alta.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Configuración inicial compleja.</span><br />
</li>
</ul>
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">⭐ Valoración:</span> 9/10</span><br />
 <br />
<hr class="mycode_hr" />
<br />
<span style="color: #2980b9;" class="mycode_color"><span style="font-size: x-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">3. Ahrefs Webmaster Tools</span></span></span><br />
<br />
<span style="color: #f39c12;" class="mycode_color"><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">¿Qué es?</span></span></span><br />
<br />
<span style="font-size: large;" class="mycode_size">Versión gratuita de Ahrefs para sitios verificados. Ofrece auditorías SEO y análisis de backlinks.</span><br />
<br />
<br />
<span style="color: #27ae60;" class="mycode_color"><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">✅ Lo bueno</span></span></span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size">Excelente para backlinks.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Auditorías técnicas avanzadas.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Interfaz profesional.</span><br />
</li>
</ul>
<br />
<span style="color: #e74c3c;" class="mycode_color"><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">❌ Lo malo</span></span></span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size">Solo funciona en webs verificadas.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Muchas funciones están reservadas para usuarios premium.</span><br />
</li>
</ul>
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">⭐ Valoración:</span> 9/10</span><br />
 <br />
<hr class="mycode_hr" />
<br />
<span style="color: #2980b9;" class="mycode_color"><span style="font-size: x-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">4. Google Trends</span></span></span><br />
<br />
<span style="font-size: large;" class="mycode_size"><span style="color: #27ae60;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">✅ Lo bueno</span></span></span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size">Detecta tendencias antes que la competencia.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Ideal para encontrar nichos.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Muy fácil de usar.</span><br />
</li>
</ul>
<br />
<span style="color: #e74c3c;" class="mycode_color"><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">❌ Lo malo</span></span></span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size">No muestra volúmenes exactos.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">No sirve para análisis SEO profundo.</span><br />
</li>
</ul>
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">⭐ Valoración:</span> 8/10</span><br />
 <br />
<hr class="mycode_hr" />
<br />
<span style="color: #2980b9;" class="mycode_color"><span style="font-size: x-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">5. Google Keyword Planner</span></span></span><br />
<br />
<span style="color: #27ae60;" class="mycode_color"><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">✅ Lo bueno</span></span></span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size">Datos directamente de Google.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Volúmenes de búsqueda fiables.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Perfecto para keywords.</span><br />
</li>
</ul>
<br />
<span style="color: #e74c3c;" class="mycode_color"><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">❌ Lo malo</span></span></span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size">Necesita cuenta de Google Ads.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Los rangos de búsqueda pueden ser amplios.</span><br />
</li>
</ul>
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">⭐ Valoración:</span> 9/10</span><br />
 <br />
<hr class="mycode_hr" />
<br />
<span style="color: #2980b9;" class="mycode_color"><span style="font-size: x-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">6. Screaming Frog SEO Spider</span></span></span><br />
<br />
<span style="color: #27ae60;" class="mycode_color"><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">✅ Lo bueno</span></span></span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size">Auditorías SEO profesionales.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Detecta errores técnicos rápidamente.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Hasta 500 URLs gratis.</span><br />
</li>
</ul>
<br />
<span style="color: #e74c3c;" class="mycode_color"><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">❌ Lo malo</span></span></span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size">Consume recursos del PC.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">La interfaz parece antigua.</span><br />
</li>
</ul>
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">⭐ Valoración:</span> 9/10</span><br />
 <br />
<hr class="mycode_hr" />
<br />
<span style="color: #2980b9;" class="mycode_color"><span style="font-size: x-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">7. PageSpeed Insights</span></span></span><br />
<br />
<span style="color: #27ae60;" class="mycode_color"><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">✅ Lo bueno</span></span></span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size">Analiza velocidad y Core Web Vitals.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Datos oficiales de Google.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Ofrece recomendaciones concretas.</span><br />
</li>
</ul>
<br />
<span style="color: #e74c3c;" class="mycode_color"><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">❌ Lo malo</span></span></span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size">Algunas recomendaciones son técnicas.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Puede variar entre análisis.</span><br />
</li>
</ul>
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">⭐ Valoración:</span> 9/10</span><br />
 <br />
<hr class="mycode_hr" />
<br />
<span style="color: #2980b9;" class="mycode_color"><span style="font-size: x-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">8. Bing Webmaster Tools</span></span></span><br />
<br />
<span style="color: #27ae60;" class="mycode_color"><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">✅ Lo bueno</span></span></span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size">Alternativa gratuita a Search Console.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Incluye auditorías SEO.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Datos adicionales de Bing.</span><br />
</li>
</ul>
<br />
<span style="color: #e74c3c;" class="mycode_color"><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">❌ Lo malo</span></span></span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size">Menos tráfico que Google.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Menos popular entre webmasters.</span><br />
</li>
</ul>
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">⭐ Valoración:</span> 8/10</span><br />
 <br />
<hr class="mycode_hr" />
<br />
<span style="color: #2980b9;" class="mycode_color"><span style="font-size: x-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">9. Microsoft Clarity</span></span></span><br />
<br />
<span style="color: #27ae60;" class="mycode_color"><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">✅ Lo bueno</span></span></span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size">Mapas de calor gratuitos.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Grabaciones de sesiones.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Muy fácil de instalar.</span><br />
</li>
</ul>
<br />
<span style="color: #e74c3c;" class="mycode_color"><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">❌ Lo malo</span></span></span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size">No sustituye a Analytics.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Menos métricas avanzadas.</span><br />
</li>
</ul>
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">⭐ Valoración:</span> 9/10</span><br />
 <br />
<hr class="mycode_hr" />
<br />
<span style="color: #2980b9;" class="mycode_color"><span style="font-size: x-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">10. GTmetrix</span></span></span><br />
<br />
<span style="color: #27ae60;" class="mycode_color"><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">✅ Lo bueno</span></span></span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size">Informes detallados de velocidad.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Muy visual.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Ideal para optimización web.</span><br />
</li>
</ul>
<br />
<span style="color: #e74c3c;" class="mycode_color"><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">❌ Lo malo</span></span></span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size">Funciones avanzadas limitadas.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Algunas pruebas requieren registro.</span><br />
</li>
</ul>
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">⭐ Valoración:</span> 8/10</span><br />
 <br />
<hr class="mycode_hr" />
<br />
<span style="color: #2980b9;" class="mycode_color"><span style="font-size: x-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">11. Ubersuggest</span></span></span><br />
<br />
<span style="color: #27ae60;" class="mycode_color"><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">✅ Lo bueno</span></span></span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size">Keywords y competencia.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Interfaz sencilla.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Perfecta para principiantes.</span><br />
</li>
</ul>
<br />
<span style="color: #e74c3c;" class="mycode_color"><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">❌ Lo malo</span></span></span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size">Consultas diarias limitadas.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Datos menos precisos que Ahrefs o Semrush.</span><br />
</li>
</ul>
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">⭐ Valoración:</span> 8/10</span><br />
 <br />
<hr class="mycode_hr" />
<br />
<span style="color: #2980b9;" class="mycode_color"><span style="font-size: x-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">12. AnswerThePublic</span></span></span><br />
<br />
<span style="color: #27ae60;" class="mycode_color"><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">✅ Lo bueno</span></span></span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size">Encuentra preguntas reales de usuarios.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Ideal para crear contenido.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Muy visual.</span><br />
</li>
</ul>
<br />
<span style="color: #e74c3c;" class="mycode_color"><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">❌ Lo malo</span></span></span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size">Límite diario en la versión gratuita.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">No muestra muchas métricas SEO.</span><br />
</li>
</ul>
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">⭐ Valoración:</span> 8/10</span><br />
 <br />
<hr class="mycode_hr" />
<br />
<span style="color: #2980b9;" class="mycode_color"><span style="font-size: x-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">13. Keyword Surfer</span></span></span><br />
<br />
<span style="color: #27ae60;" class="mycode_color"><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">✅ Lo bueno</span></span></span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size">Extensión gratuita para Chrome.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Volúmenes directamente en Google.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Muy rápida.</span><br />
</li>
</ul>
<br />
<span style="color: #e74c3c;" class="mycode_color"><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">❌ Lo malo</span></span></span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size">Datos aproximados.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Depende del navegador.</span><br />
</li>
</ul>
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">⭐ Valoración:</span> 8/10</span><br />
 <br />
<hr class="mycode_hr" />
<br />
<span style="color: #2980b9;" class="mycode_color"><span style="font-size: x-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">14. SEO Minion</span></span></span><br />
<br />
<span style="color: #27ae60;" class="mycode_color"><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">✅ Lo bueno</span></span></span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size">Analiza SEO On Page.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Detecta enlaces rotos.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Muy ligera.</span><br />
</li>
</ul>
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">❌ Lo malo</span></span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size">Funciones limitadas.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">No sustituye una auditoría completa.</span><br />
</li>
</ul>
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">⭐ Valoración:</span> 8/10</span><br />
 <br />
<hr class="mycode_hr" />
<br />
<span style="color: #2980b9;" class="mycode_color"><span style="font-size: x-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">15. SEOquake</span></span></span><br />
<br />
<span style="color: #27ae60;" class="mycode_color"><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">✅ Lo bueno</span></span></span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size">Métricas rápidas de cualquier web.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Análisis SERP.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Gratuita.</span><br />
</li>
</ul>
<br />
<span style="color: #e74c3c;" class="mycode_color"><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">❌ Lo malo</span></span></span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size">Interfaz algo antigua.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Puede mostrar demasiada información.</span><br />
</li>
</ul>
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">⭐ Valoración:</span> 8/10</span><br />
 <br />
<hr class="mycode_hr" />
<br />
<span style="color: #2980b9;" class="mycode_color"><span style="font-size: x-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">16. Rich Results Test</span></span></span><br />
<br />
<span style="color: #27ae60;" class="mycode_color"><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">✅ Lo bueno</span></span></span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size">Verifica datos estructurados.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Herramienta oficial de Google.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Muy útil para Schema.</span><br />
</li>
</ul>
<br />
<span style="color: #e74c3c;" class="mycode_color"><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">❌ Lo malo</span></span></span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size">Solo analiza marcado estructurado.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">No hace auditorías completas.</span><br />
</li>
</ul>
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">⭐ Valoración:</span> 8/10</span><br />
 <br />
<hr class="mycode_hr" />
<br />
<span style="color: #2980b9;" class="mycode_color"><span style="font-size: x-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">17. Wappalyzer</span></span></span><br />
<br />
<span style="color: #27ae60;" class="mycode_color"><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">✅ Lo bueno</span></span></span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size">Identifica tecnologías usadas por una web.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Ideal para analizar competidores.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Muy rápida.</span><br />
</li>
</ul>
<br />
<span style="color: #e74c3c;" class="mycode_color"><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">❌ Lo malo</span></span></span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size">No es una herramienta SEO pura.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Algunas detecciones pueden fallar.</span><br />
</li>
</ul>
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">⭐ Valoración:</span> 7/10</span><br />
 <br />
<hr class="mycode_hr" />
<br />
<span style="color: #2980b9;" class="mycode_color"><span style="font-size: x-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">18. Cloudflare</span></span></span><br />
<br />
<span style="color: #27ae60;" class="mycode_color"><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">✅ Lo bueno</span></span></span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size">Mejora velocidad y seguridad.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">CDN gratuito.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Protección contra ataques.</span><br />
</li>
</ul>
<br />
<span style="color: #e74c3c;" class="mycode_color"><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">❌ Lo malo</span></span></span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size">Configuración avanzada para algunos usuarios.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Puede causar errores si se configura mal.</span><br />
</li>
</ul>
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">⭐ Valoración:</span> 9/10</span><br />
 <br />
<hr class="mycode_hr" />
<br />
<span style="color: #2980b9;" class="mycode_color"><span style="font-size: x-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">19. ChatGPT</span></span></span><br />
<br />
<span style="color: #27ae60;" class="mycode_color"><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">✅ Lo bueno</span></span></span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size">Genera ideas de contenido.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Ayuda con títulos y meta descripciones.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Ahorra mucho tiempo.</span><br />
</li>
</ul>
<br />
<span style="color: #e74c3c;" class="mycode_color"><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">❌ Lo malo</span></span></span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size">Puede cometer errores.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Necesita supervisión humana.</span><br />
</li>
</ul>
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">⭐ Valoración:</span> 9/10</span><br />
 <br />
<hr class="mycode_hr" />
<br />
<span style="color: #2980b9;" class="mycode_color"><span style="font-size: x-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">20. Looker Studio</span></span></span><br />
<br />
<span style="color: #27ae60;" class="mycode_color"><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">✅ Lo bueno</span></span></span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size">Dashboards profesionales.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Integración con Search Console y Analytics.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Ideal para informes.</span><br />
</li>
</ul>
<br />
<span style="color: #e74c3c;" class="mycode_color"><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">❌ Lo malo</span></span></span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size">Configuración inicial algo compleja.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Requiere tiempo para dominarlo.</span><br />
</li>
</ul>
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">⭐ Valoración:</span> 8/10</span><br />
 <br />
<hr class="mycode_hr" />
<br />
<span style="color: #2980b9;" class="mycode_color"><span style="font-size: x-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Conclusión</span></span></span><br />
<br />
<span style="font-size: large;" class="mycode_size">Si tuviera que elegir solo 5 herramientas SEO gratuitas, me quedaría con Google Search Console, Google Analytics 4, Ahrefs Webmaster Tools, Screaming Frog y PageSpeed Insights.<br />
Entre todas cubren indexación, tráfico, auditorías técnicas, backlinks y velocidad web.<br />
Son la base de cualquier estrategia SEO moderna.</span><br />
<br />
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">¿Cuál utilizas tú?, ¿Añadirías alguna otra herramienta a la lista? Déjala en los comentarios.</span></span>]]></description>
			<content:encoded><![CDATA[<div style="text-align: center;" class="mycode_align"><span style="color: #2980b9;" class="mycode_color"><span style="font-size: x-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Las 20 Mejores Herramientas SEO Gratuitas de 2026: Ventajas, Desventajas y Valoración</span></span></span></div>
<br />
<span style="font-size: large;" class="mycode_size">Si tienes una web, blog o tienda online, estas son las herramientas SEO gratuitas que más recomiendo. He seleccionado las más útiles para investigación de palabras clave, auditorías técnicas, velocidad web, backlinks y análisis de tráfico. Muchas de ellas son utilizadas diariamente por profesionales SEO de todo el mundo. </span><br />
 <br />
<hr class="mycode_hr" />
<br />
<span style="color: #2980b9;" class="mycode_color"><span style="font-size: x-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">1. Google Search Console</span></span></span><br />
<br />
<span style="color: #f39c12;" class="mycode_color"><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">¿Qué es?</span></span></span><br />
<br />
<span style="font-size: large;" class="mycode_size">La herramienta oficial de Google para analizar el rendimiento de una web en los resultados de búsqueda.</span><br />
<br />
<br />
<span style="color: #27ae60;" class="mycode_color"><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">✅ Lo bueno</span></span></span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size">Datos oficiales de Google.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Permite detectar errores de indexación.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Muestra clics, impresiones y posiciones.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Totalmente gratuita.</span><br />
</li>
</ul>
<br />
<span style="color: #e74c3c;" class="mycode_color"><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">❌ Lo malo</span></span></span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size">No muestra datos de la competencia.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Interfaz poco amigable para principiantes.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Información limitada comparada con herramientas premium.</span><br />
</li>
</ul>
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">⭐ Valoración:</span> 10/10</span><br />
 <br />
<hr class="mycode_hr" />
<br />
<span style="color: #2980b9;" class="mycode_color"><span style="font-size: x-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">2. Google Analytics 4</span></span></span><br />
<br />
<span style="color: #f39c12;" class="mycode_color"><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">¿Qué es?</span></span></span><br />
<br />
<span style="font-size: large;" class="mycode_size">La herramienta de analítica web más utilizada para medir visitas y comportamiento de usuarios.</span><br />
<br />
<br />
<span style="color: #27ae60;" class="mycode_color"><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">✅ Lo bueno</span></span></span><ul class="mycode_list"><li>Muy completa.<br />
</li>
<li>Integración perfecta con Google.<br />
</li>
<li>Permite medir conversiones.<br />
</li>
</ul>
<br />
<span style="color: #e74c3c;" class="mycode_color"><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">❌ Lo malo</span></span></span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size">Curva de aprendizaje alta.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Configuración inicial compleja.</span><br />
</li>
</ul>
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">⭐ Valoración:</span> 9/10</span><br />
 <br />
<hr class="mycode_hr" />
<br />
<span style="color: #2980b9;" class="mycode_color"><span style="font-size: x-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">3. Ahrefs Webmaster Tools</span></span></span><br />
<br />
<span style="color: #f39c12;" class="mycode_color"><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">¿Qué es?</span></span></span><br />
<br />
<span style="font-size: large;" class="mycode_size">Versión gratuita de Ahrefs para sitios verificados. Ofrece auditorías SEO y análisis de backlinks.</span><br />
<br />
<br />
<span style="color: #27ae60;" class="mycode_color"><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">✅ Lo bueno</span></span></span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size">Excelente para backlinks.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Auditorías técnicas avanzadas.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Interfaz profesional.</span><br />
</li>
</ul>
<br />
<span style="color: #e74c3c;" class="mycode_color"><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">❌ Lo malo</span></span></span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size">Solo funciona en webs verificadas.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Muchas funciones están reservadas para usuarios premium.</span><br />
</li>
</ul>
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">⭐ Valoración:</span> 9/10</span><br />
 <br />
<hr class="mycode_hr" />
<br />
<span style="color: #2980b9;" class="mycode_color"><span style="font-size: x-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">4. Google Trends</span></span></span><br />
<br />
<span style="font-size: large;" class="mycode_size"><span style="color: #27ae60;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b">✅ Lo bueno</span></span></span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size">Detecta tendencias antes que la competencia.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Ideal para encontrar nichos.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Muy fácil de usar.</span><br />
</li>
</ul>
<br />
<span style="color: #e74c3c;" class="mycode_color"><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">❌ Lo malo</span></span></span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size">No muestra volúmenes exactos.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">No sirve para análisis SEO profundo.</span><br />
</li>
</ul>
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">⭐ Valoración:</span> 8/10</span><br />
 <br />
<hr class="mycode_hr" />
<br />
<span style="color: #2980b9;" class="mycode_color"><span style="font-size: x-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">5. Google Keyword Planner</span></span></span><br />
<br />
<span style="color: #27ae60;" class="mycode_color"><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">✅ Lo bueno</span></span></span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size">Datos directamente de Google.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Volúmenes de búsqueda fiables.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Perfecto para keywords.</span><br />
</li>
</ul>
<br />
<span style="color: #e74c3c;" class="mycode_color"><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">❌ Lo malo</span></span></span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size">Necesita cuenta de Google Ads.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Los rangos de búsqueda pueden ser amplios.</span><br />
</li>
</ul>
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">⭐ Valoración:</span> 9/10</span><br />
 <br />
<hr class="mycode_hr" />
<br />
<span style="color: #2980b9;" class="mycode_color"><span style="font-size: x-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">6. Screaming Frog SEO Spider</span></span></span><br />
<br />
<span style="color: #27ae60;" class="mycode_color"><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">✅ Lo bueno</span></span></span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size">Auditorías SEO profesionales.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Detecta errores técnicos rápidamente.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Hasta 500 URLs gratis.</span><br />
</li>
</ul>
<br />
<span style="color: #e74c3c;" class="mycode_color"><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">❌ Lo malo</span></span></span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size">Consume recursos del PC.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">La interfaz parece antigua.</span><br />
</li>
</ul>
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">⭐ Valoración:</span> 9/10</span><br />
 <br />
<hr class="mycode_hr" />
<br />
<span style="color: #2980b9;" class="mycode_color"><span style="font-size: x-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">7. PageSpeed Insights</span></span></span><br />
<br />
<span style="color: #27ae60;" class="mycode_color"><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">✅ Lo bueno</span></span></span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size">Analiza velocidad y Core Web Vitals.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Datos oficiales de Google.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Ofrece recomendaciones concretas.</span><br />
</li>
</ul>
<br />
<span style="color: #e74c3c;" class="mycode_color"><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">❌ Lo malo</span></span></span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size">Algunas recomendaciones son técnicas.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Puede variar entre análisis.</span><br />
</li>
</ul>
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">⭐ Valoración:</span> 9/10</span><br />
 <br />
<hr class="mycode_hr" />
<br />
<span style="color: #2980b9;" class="mycode_color"><span style="font-size: x-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">8. Bing Webmaster Tools</span></span></span><br />
<br />
<span style="color: #27ae60;" class="mycode_color"><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">✅ Lo bueno</span></span></span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size">Alternativa gratuita a Search Console.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Incluye auditorías SEO.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Datos adicionales de Bing.</span><br />
</li>
</ul>
<br />
<span style="color: #e74c3c;" class="mycode_color"><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">❌ Lo malo</span></span></span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size">Menos tráfico que Google.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Menos popular entre webmasters.</span><br />
</li>
</ul>
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">⭐ Valoración:</span> 8/10</span><br />
 <br />
<hr class="mycode_hr" />
<br />
<span style="color: #2980b9;" class="mycode_color"><span style="font-size: x-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">9. Microsoft Clarity</span></span></span><br />
<br />
<span style="color: #27ae60;" class="mycode_color"><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">✅ Lo bueno</span></span></span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size">Mapas de calor gratuitos.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Grabaciones de sesiones.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Muy fácil de instalar.</span><br />
</li>
</ul>
<br />
<span style="color: #e74c3c;" class="mycode_color"><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">❌ Lo malo</span></span></span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size">No sustituye a Analytics.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Menos métricas avanzadas.</span><br />
</li>
</ul>
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">⭐ Valoración:</span> 9/10</span><br />
 <br />
<hr class="mycode_hr" />
<br />
<span style="color: #2980b9;" class="mycode_color"><span style="font-size: x-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">10. GTmetrix</span></span></span><br />
<br />
<span style="color: #27ae60;" class="mycode_color"><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">✅ Lo bueno</span></span></span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size">Informes detallados de velocidad.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Muy visual.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Ideal para optimización web.</span><br />
</li>
</ul>
<br />
<span style="color: #e74c3c;" class="mycode_color"><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">❌ Lo malo</span></span></span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size">Funciones avanzadas limitadas.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Algunas pruebas requieren registro.</span><br />
</li>
</ul>
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">⭐ Valoración:</span> 8/10</span><br />
 <br />
<hr class="mycode_hr" />
<br />
<span style="color: #2980b9;" class="mycode_color"><span style="font-size: x-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">11. Ubersuggest</span></span></span><br />
<br />
<span style="color: #27ae60;" class="mycode_color"><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">✅ Lo bueno</span></span></span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size">Keywords y competencia.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Interfaz sencilla.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Perfecta para principiantes.</span><br />
</li>
</ul>
<br />
<span style="color: #e74c3c;" class="mycode_color"><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">❌ Lo malo</span></span></span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size">Consultas diarias limitadas.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Datos menos precisos que Ahrefs o Semrush.</span><br />
</li>
</ul>
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">⭐ Valoración:</span> 8/10</span><br />
 <br />
<hr class="mycode_hr" />
<br />
<span style="color: #2980b9;" class="mycode_color"><span style="font-size: x-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">12. AnswerThePublic</span></span></span><br />
<br />
<span style="color: #27ae60;" class="mycode_color"><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">✅ Lo bueno</span></span></span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size">Encuentra preguntas reales de usuarios.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Ideal para crear contenido.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Muy visual.</span><br />
</li>
</ul>
<br />
<span style="color: #e74c3c;" class="mycode_color"><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">❌ Lo malo</span></span></span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size">Límite diario en la versión gratuita.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">No muestra muchas métricas SEO.</span><br />
</li>
</ul>
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">⭐ Valoración:</span> 8/10</span><br />
 <br />
<hr class="mycode_hr" />
<br />
<span style="color: #2980b9;" class="mycode_color"><span style="font-size: x-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">13. Keyword Surfer</span></span></span><br />
<br />
<span style="color: #27ae60;" class="mycode_color"><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">✅ Lo bueno</span></span></span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size">Extensión gratuita para Chrome.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Volúmenes directamente en Google.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Muy rápida.</span><br />
</li>
</ul>
<br />
<span style="color: #e74c3c;" class="mycode_color"><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">❌ Lo malo</span></span></span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size">Datos aproximados.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Depende del navegador.</span><br />
</li>
</ul>
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">⭐ Valoración:</span> 8/10</span><br />
 <br />
<hr class="mycode_hr" />
<br />
<span style="color: #2980b9;" class="mycode_color"><span style="font-size: x-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">14. SEO Minion</span></span></span><br />
<br />
<span style="color: #27ae60;" class="mycode_color"><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">✅ Lo bueno</span></span></span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size">Analiza SEO On Page.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Detecta enlaces rotos.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Muy ligera.</span><br />
</li>
</ul>
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">❌ Lo malo</span></span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size">Funciones limitadas.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">No sustituye una auditoría completa.</span><br />
</li>
</ul>
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">⭐ Valoración:</span> 8/10</span><br />
 <br />
<hr class="mycode_hr" />
<br />
<span style="color: #2980b9;" class="mycode_color"><span style="font-size: x-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">15. SEOquake</span></span></span><br />
<br />
<span style="color: #27ae60;" class="mycode_color"><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">✅ Lo bueno</span></span></span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size">Métricas rápidas de cualquier web.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Análisis SERP.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Gratuita.</span><br />
</li>
</ul>
<br />
<span style="color: #e74c3c;" class="mycode_color"><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">❌ Lo malo</span></span></span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size">Interfaz algo antigua.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Puede mostrar demasiada información.</span><br />
</li>
</ul>
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">⭐ Valoración:</span> 8/10</span><br />
 <br />
<hr class="mycode_hr" />
<br />
<span style="color: #2980b9;" class="mycode_color"><span style="font-size: x-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">16. Rich Results Test</span></span></span><br />
<br />
<span style="color: #27ae60;" class="mycode_color"><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">✅ Lo bueno</span></span></span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size">Verifica datos estructurados.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Herramienta oficial de Google.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Muy útil para Schema.</span><br />
</li>
</ul>
<br />
<span style="color: #e74c3c;" class="mycode_color"><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">❌ Lo malo</span></span></span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size">Solo analiza marcado estructurado.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">No hace auditorías completas.</span><br />
</li>
</ul>
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">⭐ Valoración:</span> 8/10</span><br />
 <br />
<hr class="mycode_hr" />
<br />
<span style="color: #2980b9;" class="mycode_color"><span style="font-size: x-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">17. Wappalyzer</span></span></span><br />
<br />
<span style="color: #27ae60;" class="mycode_color"><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">✅ Lo bueno</span></span></span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size">Identifica tecnologías usadas por una web.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Ideal para analizar competidores.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Muy rápida.</span><br />
</li>
</ul>
<br />
<span style="color: #e74c3c;" class="mycode_color"><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">❌ Lo malo</span></span></span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size">No es una herramienta SEO pura.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Algunas detecciones pueden fallar.</span><br />
</li>
</ul>
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">⭐ Valoración:</span> 7/10</span><br />
 <br />
<hr class="mycode_hr" />
<br />
<span style="color: #2980b9;" class="mycode_color"><span style="font-size: x-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">18. Cloudflare</span></span></span><br />
<br />
<span style="color: #27ae60;" class="mycode_color"><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">✅ Lo bueno</span></span></span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size">Mejora velocidad y seguridad.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">CDN gratuito.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Protección contra ataques.</span><br />
</li>
</ul>
<br />
<span style="color: #e74c3c;" class="mycode_color"><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">❌ Lo malo</span></span></span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size">Configuración avanzada para algunos usuarios.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Puede causar errores si se configura mal.</span><br />
</li>
</ul>
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">⭐ Valoración:</span> 9/10</span><br />
 <br />
<hr class="mycode_hr" />
<br />
<span style="color: #2980b9;" class="mycode_color"><span style="font-size: x-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">19. ChatGPT</span></span></span><br />
<br />
<span style="color: #27ae60;" class="mycode_color"><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">✅ Lo bueno</span></span></span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size">Genera ideas de contenido.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Ayuda con títulos y meta descripciones.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Ahorra mucho tiempo.</span><br />
</li>
</ul>
<br />
<span style="color: #e74c3c;" class="mycode_color"><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">❌ Lo malo</span></span></span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size">Puede cometer errores.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Necesita supervisión humana.</span><br />
</li>
</ul>
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">⭐ Valoración:</span> 9/10</span><br />
 <br />
<hr class="mycode_hr" />
<br />
<span style="color: #2980b9;" class="mycode_color"><span style="font-size: x-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">20. Looker Studio</span></span></span><br />
<br />
<span style="color: #27ae60;" class="mycode_color"><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">✅ Lo bueno</span></span></span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size">Dashboards profesionales.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Integración con Search Console y Analytics.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Ideal para informes.</span><br />
</li>
</ul>
<br />
<span style="color: #e74c3c;" class="mycode_color"><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">❌ Lo malo</span></span></span><ul class="mycode_list"><li><span style="font-size: large;" class="mycode_size">Configuración inicial algo compleja.</span><br />
</li>
<li><span style="font-size: large;" class="mycode_size">Requiere tiempo para dominarlo.</span><br />
</li>
</ul>
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">⭐ Valoración:</span> 8/10</span><br />
 <br />
<hr class="mycode_hr" />
<br />
<span style="color: #2980b9;" class="mycode_color"><span style="font-size: x-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Conclusión</span></span></span><br />
<br />
<span style="font-size: large;" class="mycode_size">Si tuviera que elegir solo 5 herramientas SEO gratuitas, me quedaría con Google Search Console, Google Analytics 4, Ahrefs Webmaster Tools, Screaming Frog y PageSpeed Insights.<br />
Entre todas cubren indexación, tráfico, auditorías técnicas, backlinks y velocidad web.<br />
Son la base de cualquier estrategia SEO moderna.</span><br />
<br />
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">¿Cuál utilizas tú?, ¿Añadirías alguna otra herramienta a la lista? Déjala en los comentarios.</span></span>]]></content:encoded>
		</item>
	</channel>
</rss>