Files
pflores.linkedcorp.net/PROMPT_IA.md
T
codeuploader 5846c515f3 feat: sitio CV completo v1.0.0
- 4 temas WordPress: persona-cv (activo), lumina, apex-cv, cvolio
- Plugin pflores-cv-fields con CMB2 (100% gratuito) — admin editable
- Generador PDF dinámico con Chromium headless (?cv_pdf=1)
- Datos del CV de Patricia Flores cargados en CMB2
- URL dinámica con soporte proxy SSL (NPM/X-Forwarded-Proto)
- WP Mail SMTP instalado (pendiente config SMTP)
- Documentación completa: PROMPT_IA.md, DEPLOY_WEB.md, PRODUCCION.md, VERSIONADO.md
2026-06-05 11:21:30 -05:00

27 KiB

PROMPT_IA — Guía completa del proyecto pflores.linkedcorp.net

Documento de referencia para asistentes de IA. Léelo completo antes de cualquier tarea. Última actualización: junio 2026.


1. ¿Qué es este proyecto?

Sitio web personal de hoja de vida / currículum ejecutivo de Patricia Soledad Flores Sánchez, gerente de operaciones financieras con 22+ años en banca y microfinanzas (Ecuador).

  • URL pública: https://pflores.linkedcorp.net
  • Stack: WordPress 6.x + PHP 8.4 + MariaDB + CMB2 (campos personalizados, 100 % gratuito)
  • Se ejecuta con el servidor PHP incorporado (php -S) en el puerto 8081
  • SSL terminado por Nginx Proxy Manager → envía X-Forwarded-Proto: https
  • IP local del servidor: 192.168.222.40

2. Estructura de directorios

pflores.linkedcorp.net/
├── backend/
│   ├── start-wordpress.sh          # Arrancar el servidor PHP
│   └── wordpress/                  # Instalación WordPress
│       ├── wp-config.php           # Config dinámica (URL, auto-updates OFF)
│       └── wp-content/
│           ├── plugins/
│           │   ├── cmb2/           # CMB2 — campos personalizados (GRATIS)
│           │   └── pflores-cv-fields/
│           │       ├── pflores-cv-fields.php   # Menú admin + campos CMB2
│           │       ├── pdf-generator.php       # Generador PDF con Chromium
│           │       └── populate-data.php       # Sembrador inicial (ejecutar 1 vez)
│           └── themes/
│               ├── persona-cv/     # ACTIVO — Personage-style, rojo, timeline central
│               ├── apex-cv/        # Dark, cian, sidebar fijo izquierdo
│               ├── lumina -> ../../frontend/lumina-cv-theme    # symlink
│               ├── cvolio -> ../../frontend/cvfolio-theme      # symlink
│               └── ...
├── frontend/
│   ├── persona-cv-theme/           # Fuente del tema activo (usa symlink persona-cv)
│   │   ├── style.css               # Solo cabecera del tema
│   │   ├── functions.php           # Setup, enqueue, helpers
│   │   ├── header.php              # Header con nav y botón PDF
│   │   ├── footer.php
│   │   ├── front-page.php          # PLANTILLA PRINCIPAL — toda la página CV
│   │   ├── index.php               # Fallback
│   │   ├── assets/css/theme.css    # Estilos completos
│   │   ├── assets/js/theme.js      # JS (nav, scroll spy, animaciones)
│   │   ├── assets/images/          # patricia-flores-profile.jpeg, qr.png
│   │   ├── assets/docs/            # CV_Patricia_Flores_Sanchez_ES_FINAL.docx
│   │   └── inc/
│   │       ├── cv-data.php         # Fallback hardcodeado (función persona_cv_data())
│   │       ├── customizer.php      # Campos Customizer (mínimos)
│   │       └── visits.php          # Contador de visitas
│   ├── lumina-cv-theme/            # Tema claro teal+ámbar, sidebar izquierdo
│   ├── cvfolio-theme/              # Tema oscuro glassmorphism (original)
│   └── apex-cv-theme/              # OBSOLETO — usar wp-content/themes/apex-cv
├── docs/
│   └── instalacion-wordpress.md
├── .env                            # Variables de entorno (DB, puerto, etc.)
├── PROMPT_IA.md                    # ESTE ARCHIVO
└── README.md

NOTA IMPORTANTE: El tema apex-cv vive directamente en backend/wordpress/wp-content/themes/apex-cv/ (directorio real, no symlink) porque el directorio frontend/apex-cv-theme/ tiene un problema de persistencia. Los demás temas activos usan symlinks desde wp-content/themes/ hacia frontend/.


3. Base de datos

Host:     192.168.222.20
DB:       paty.wordpress
Usuario:  paty.wordpress
Password: paty.wordpress
Prefijo:  cv_          → tabla principal: cv_options

Conexión de prueba:

mysql -u "paty.wordpress" -p"paty.wordpress" -h 192.168.222.20 "paty.wordpress" --ssl=0

4. Arrancar / reiniciar el servidor

# Ver si está corriendo
lsof -i tcp:8081

# Matar proceso existente
kill $(lsof -ti tcp:8081)

# Arrancar (lee variables de .env automáticamente)
bash backend/start-wordpress.sh &

El servidor escucha en 0.0.0.0:8081 (todas las interfaces) gracias a WP_HOST=0.0.0.0 en .env.


5. Plugins activos y su función

Plugin Propósito Gratuito
cmb2/init.php Campos personalizados en el admin (repeaters, options pages) ✓ GPL
pflores-cv-fields/pflores-cv-fields.php Páginas de opciones + función pflores_get_cv_data() + PDF ✓ propio

Activar / verificar plugins en la BD:

mysql -u "paty.wordpress" -p"paty.wordpress" -h 192.168.222.20 "paty.wordpress" --ssl=0 \
  -e "SELECT option_value FROM cv_options WHERE option_name='active_plugins';"

El valor correcto debe ser:

a:2:{i:0;s:13:"cmb2/init.php";i:1;s:39:"pflores-cv-fields/pflores-cv-fields.php";}

Si no, corregirlo:

mysql -u "paty.wordpress" -p"paty.wordpress" -h 192.168.222.20 "paty.wordpress" --ssl=0 \
  -e "UPDATE cv_options SET option_value='a:2:{i:0;s:13:\"cmb2/init.php\";i:1;s:39:\"pflores-cv-fields/pflores-cv-fields.php\";}' WHERE option_name='active_plugins';"

⚠ La serialización PHP es estricta: s:N: donde N es la longitud exacta en bytes. Siempre genera el valor con php -r "echo serialize(['cmb2/init.php','pflores-cv-fields/pflores-cv-fields.php']);".


6. Cambiar el tema activo

mysql -u "paty.wordpress" -p"paty.wordpress" -h 192.168.222.20 "paty.wordpress" --ssl=0 \
  -e "UPDATE cv_options SET option_value='SLUG_TEMA' WHERE option_name IN('template','stylesheet');"
Slug Tema
persona-cv Activo por defecto — Personage-style, secciones alternas, rojo
lumina Claro, teal+ámbar, sidebar izquierdo, foto circular
apex-cv Oscuro, cian eléctrico, sidebar fijo
cvolio Oscuro glassmorphism, paleta café/tostado

7. Arquitectura de datos — CMB2

Todos los datos del CV se almacenan en wp_options (prefijo cv_) como arrays PHP serializados. Se acceden con get_option('clave').

Clave wp_options Contenido
pflores_perfil Nombre, cargo, intro, resumen, contacto, foto
pflores_experiencia Array de cargos con bullets
pflores_formacion Títulos académicos + certificaciones
pflores_competencias Grupos de habilidades con porcentajes
pflores_extras Métricas, highlights, impacto, voluntariado

Función central de lectura:

pflores_get_cv_data(): array
// Retorna la misma estructura que todos los temas esperan.
// Si CMB2 no está disponible, devuelve pflores_cv_fallback_data().

Estructura del array retornado:

[
  'hero'           => ['name','role','role2','intro','location','email',
                       'phone','linkedin','availability','focus','languages',
                       'born','id','web','eyebrow'],
  'photo'          => 'URL de la imagen de perfil (o vacío)',
  'summary'        => ['title','body'],
  'metrics'        => [['value','suffix','label'], ...],   // 5 contadores
  'highlights'     => [['value','suffix','label'], ...],   // 4 logros grandes
  'impact'         => [['title','body'], ...],             // 3 áreas
  'experience'     => [['period','title','company','location','lead','bullets'=>[...]], ...],
  'education'      => [['year','title','institution','detail'], ...],
  'certifications' => [['year','title','issuer'], ...],
  'competencies'   => ['Grupo' => [['name','pct'], ...], ...],
  'volunteer'      => ['title','year','body'],
  'additional'     => ['Idiomas'=>'...','Disponibilidad'=>'...','C.I.'=>'...', ...],
]

8. Editar datos del CV desde el admin

URL del admin: https://pflores.linkedcorp.net/wp-admin

  • Usuario: pflores
  • Contraseña: en .env como WP_ADMIN_PASSWORD

En el menú lateral aparece "CV Patricia Flores" con sub-páginas:

  • Perfil → datos personales, foto, disponibilidad
  • Experiencia → cargos (repeater, arrastrable)
  • Formación → títulos + certificaciones
  • Competencias → grupos de habilidades con porcentajes
  • Métricas / Impacto → contadores, logros, áreas de impacto, voluntariado

9. Agregar un nuevo campo al CV

9a. Campo simple (texto, email, URL)

Paso 1 — Registrar el campo en pflores-cv-fields.php dentro de la función pflores_register_pages():

// Ejemplo: añadir "Twitter/X" al perfil
$perfil->add_field([
    'id'   => 'pf_twitter',
    'name' => 'Twitter / X URL',
    'type' => 'text_url',
]);

Paso 2 — Añadir la lectura en pflores_get_cv_data():

'hero' => [
    // ... campos existentes ...
    'twitter' => $perfil['pf_twitter'] ?? '',
],

Paso 3 — Usarlo en el front-page.php de cada tema:

$twitter = $hero['twitter'] ?? '';
if ($twitter) : ?>
    <a href="<?php echo esc_url($twitter); ?>">Twitter</a>
<?php endif; ?>

Paso 4 — Si el campo debe aparecer en el PDF, añadirlo en pdf-generator.php dentro de pflores_build_cv_html().


9b. Nuevo grupo repetible (como experiencia o certificaciones)

Paso 1 — Registrar un nuevo CMB2 box con group en pflores_register_pages():

$premios = new_cmb2_box([
    'id'           => 'pflores_premios',
    'title'        => 'Premios y reconocimientos',
    'object_types' => ['options-page'],
    'option_key'   => 'pflores_premios',   // nombre de la opción en BD
    'parent_slug'  => 'pflores_perfil',    // sub-menú bajo el menú principal
    'menu_title'   => 'Premios',
    'save_button'  => 'Guardar cambios',
    'capability'   => 'manage_options',
]);

$gr = $premios->add_field([
    'id'      => 'pf_awards',
    'type'    => 'group',
    'options' => ['group_title' => 'Premio {#}', 'add_button' => 'Añadir premio',
                  'remove_button' => 'Eliminar', 'sortable' => true, 'closed' => true],
]);
$premios->add_group_field($gr, ['id' => 'year',  'name' => 'Año',         'type' => 'text']);
$premios->add_group_field($gr, ['id' => 'title', 'name' => 'Título',      'type' => 'text']);
$premios->add_group_field($gr, ['id' => 'org',   'name' => 'Organización','type' => 'text']);

Paso 2 — Leer los datos en pflores_get_cv_data():

$premiosOpts = get_option('pflores_premios', []);
$awards = [];
foreach ((array) ($premiosOpts['pf_awards'] ?? []) as $item) {
    $awards[] = ['year' => $item['year'] ?? '', 'title' => $item['title'] ?? '', 'org' => $item['org'] ?? ''];
}
// Agregar 'awards' => $awards al array retornado

Paso 3 — Renderizarlo en front-page.php de cada tema.

Paso 4 — Poblar datos iniciales añadiendo al populate-data.php:

update_option('pflores_premios', [
    'pf_awards' => [
        ['year' => '2025', 'title' => 'Premio Excelencia', 'org' => 'Fundación FACES'],
    ],
]);

10. Modificar datos existentes

Opción A — Desde el admin de WordPress (recomendado):

  • Ir a wp-admin → CV Patricia Flores → sub-página correspondiente → editar → Guardar.

Opción B — Directo en BD (para migraciones o correcciones masivas):

mysql -u "paty.wordpress" -p"paty.wordpress" -h 192.168.222.20 "paty.wordpress" --ssl=0 -e "
UPDATE cv_options SET option_value = 'Nuevo valor' WHERE option_name = 'pflores_perfil';
"

Para campos dentro de arrays (repeaters), es más fácil editar desde el admin o re-ejecutar populate-data.php.

Re-ejecutar el poblador de datos (si se necesita resetear todo):

https://pflores.linkedcorp.net/wp-content/plugins/pflores-cv-fields/populate-data.php?key=pflores2024

⚠ Esto sobreescribe TODOS los datos con los valores del archivo populate-data.php.


11. Crear un nuevo tema

Convenciones obligatorias

  1. Directorio: Crear en frontend/NOMBRE-cv-theme/ con subdirectorios assets/{css,js,images,docs} e inc/.
  2. Symlink: ln -s /ruta/absoluta/frontend/NOMBRE-cv-theme /ruta/wordpress/wp-content/themes/NOMBRE-cv
  3. Text Domain: usar nombre (minúsculas, sin guiones).
  4. Prefijo de funciones: nombre_ (ej: nova_setup(), nova_render_nav()).
  5. Prefijo CSS: nv- (2-3 letras, sin conflictos con pn-, lm-, ax-, cv-).

Archivos mínimos requeridos

NOMBRE-cv-theme/
├── style.css          # Cabecera del tema (Theme Name, Text Domain, Version...)
├── functions.php      # apex_setup, enqueue, nav helpers
├── header.php         # <html><head> + nav + botón PDF
├── footer.php         # </body></html>
├── front-page.php     # TODA la lógica y HTML del CV
├── index.php          # Fallback vacío o mínimo
└── inc/
    ├── cv-data.php    # Función NOMBRE_cv_data() con fallback hardcodeado
    ├── customizer.php # Opcional, puede estar vacío
    └── visits.php     # Contador de visitas (copiar de otro tema y renombrar funciones)

Estructura obligatoria de functions.php

<?php
declare(strict_types=1);

require_once get_template_directory() . '/inc/customizer.php';
require_once get_template_directory() . '/inc/cv-data.php';
require_once get_template_directory() . '/inc/visits.php';

function NOMBRE_setup(): void { /* add_theme_support, register_nav_menus */ }
add_action('after_setup_theme', 'NOMBRE_setup');

function NOMBRE_enqueue_assets(): void {
    // Cargar Google Font + CSS + JS
    wp_enqueue_style('NOMBRE-fonts', 'https://fonts.googleapis.com/...', [], null);
    wp_enqueue_style('NOMBRE-theme', get_template_directory_uri() . '/assets/css/theme.css', ['NOMBRE-fonts'], '1.0.0');
    wp_enqueue_script('NOMBRE-theme', get_template_directory_uri() . '/assets/js/theme.js', [], '1.0.0', true);
}
add_action('wp_enqueue_scripts', 'NOMBRE_enqueue_assets');

function NOMBRE_render_nav(): string { /* nav links con IDs de sección */ }

Estructura obligatoria de front-page.php

<?php
declare(strict_types=1);
get_header();

// ► SIEMPRE usar esta línea para obtener los datos:
$cv = function_exists('pflores_get_cv_data') ? pflores_get_cv_data() : NOMBRE_cv_data();

$hero           = $cv['hero'];
$metrics        = $cv['metrics'];
$highlights     = $cv['highlights'];
$summary        = $cv['summary'];
$impact         = $cv['impact'];
$experience     = $cv['experience'];
$education      = $cv['education'];
$certifications = $cv['certifications'];
$competencies   = $cv['competencies'];
$volunteer      = $cv['volunteer'];
$additional     = $cv['additional'];

// Foto de perfil: ACF primero, si no la imagen local
$acfPhoto     = $cv['photo'] ?? '';
$profileImage = $acfPhoto ?: get_template_directory_uri() . '/assets/images/patricia-flores-profile.jpeg';

// Archivos
$cvFile  = get_template_directory_uri() . '/assets/docs/CV_Patricia_Flores_Sanchez_ES_FINAL.docx';
$qrImage = get_template_directory_uri() . '/assets/images/patricia-flores-qr.png';
$publicUrl = 'https://pflores.linkedcorp.net';

// Variables de conveniencia
$heroName     = $hero['name'];
$heroRole     = $hero['role'];
$heroEmail    = $hero['email'];
$heroPhone    = $hero['phone'];
$heroLocation = $hero['location'];
$linkedin     = $hero['linkedin'];

/* ... HTML del tema aquí ... */

get_footer();

Iteración sobre competencias (compatibilidad CMB2 + fallback)

Los temas deben manejar ambos formatos de competencias:

<?php foreach ($competencies as $group => $items) : ?>
    <h3><?php echo esc_html($group); ?></h3>
    <?php foreach ($items as $item) :
        // ► SIEMPRE usar esta normalización:
        $skillName = is_array($item) ? ($item['name'] ?? '') : (string) $item;
        $skillPct  = is_array($item) ? ($item['pct']  ?? 80) : 80;
    ?>
        <span><?php echo esc_html($skillName); ?></span>
        <?php // Si el tema muestra barras de progreso: ?>
        <div style="width:<?php echo esc_attr((string)$skillPct); ?>%"></div>
    <?php endforeach; ?>
<?php endforeach; ?>

Botón de descarga PDF (obligatorio en todos los temas)

<!-- En header.php o sidebar, reemplazar cualquier botón de "Imprimir" por: -->
<a class="btn-pdf" href="<?php echo esc_url(home_url('/?cv_pdf=1')); ?>" target="_blank">
    Descargar CV PDF
</a>

inc/cv-data.php — función de fallback

Debe contener todos los datos reales de Patricia Flores, idénticos a los que están en la BD. Copiar la función de otro tema y renombrar a NOMBRE_cv_data().

⚠ Las competencias del fallback deben tener formato array: ['name' => 'Gestión operativa', 'pct' => 95]

Activar el nuevo tema

# 1. Crear el symlink
ln -s /ruta/absoluta/frontend/NOMBRE-cv-theme \
      /ruta/absoluta/backend/wordpress/wp-content/themes/NOMBRE-cv

# 2. Activar en la BD
mysql -u "paty.wordpress" -p"paty.wordpress" -h 192.168.222.20 "paty.wordpress" --ssl=0 \
  -e "UPDATE cv_options SET option_value='NOMBRE-cv' WHERE option_name IN('template','stylesheet');"

⚠ Evitar el slug apex (existe un tema comercial con ese nombre en WordPress.org). Usar siempre slugs compuestos: nova-cv, slate-cv, forma-cv, etc.


12. Crear / modificar menús de navegación

Los menús de navegación son listas de anclas (#seccion) dentro del mismo tema. No se usan menús de WordPress por defecto.

Modificar los ítems del menú en un tema

En functions.php de cada tema, hay una función NOMBRE_render_nav():

function persona_render_nav(): string {
    $items = [
        '#sobre-mi'        => 'Sobre mí',
        '#impacto'         => 'Impacto',
        '#experiencia'     => 'Experiencia',
        '#formacion'       => 'Formación',
        '#competencias'    => 'Competencias',
        '#certificaciones' => 'Certificaciones',
        '#contacto'        => 'Contacto',
    ];
    // Para añadir un ítem:  '#premios' => 'Premios',
    // Para eliminar: quitar la línea correspondiente
    // Para reordenar: cambiar el orden del array
    ...
}

El href debe coincidir con el id de la sección en front-page.php:

<section id="premios"> <!-- El ID debe ser igual al href sin el # -->

Usar menús de WordPress (avanzado)

Si se registra un menú en functions.php:

register_nav_menus(['primary' => __('Menú principal', 'persona')]);

Se puede asignar desde wp-admin → Apariencia → Menús y el tema lo detectará automáticamente si has_nav_menu('primary') retorna true.


13. Generador de PDF

Endpoint: https://pflores.linkedcorp.net/?cv_pdf=1

Cómo funciona (pdf-generator.php):

  1. Se activa con get_query_var('cv_pdf') === '1'
  2. Llama a pflores_get_cv_data() para obtener todos los datos actuales
  3. Genera HTML limpio con CSS embebido (formato A4, 2 columnas)
  4. Escribe el HTML en un archivo temporal
  5. Ejecuta Chromium headless: chromium --headless --no-sandbox --print-to-pdf=... file://...
  6. Lee el PDF resultante y lo devuelve con headers de descarga
  7. Limpia los archivos temporales

Modificar el layout del PDF:

Todo el diseño está en la función pflores_build_cv_html() dentro de pdf-generator.php. Modificar el CSS dentro de la variable $css o el HTML de cada sección.

Añadir una nueva sección al PDF (ej: Premios):

// En pflores_build_cv_html(), después de certificaciones:
$awardsHtml = '';
foreach ($awards as $a) {
    $awardsHtml .= '<div class="cert-item">...';
}

// Y en el HTML final:
'<p class="sec-title">Premios y reconocimientos</p>' . $awardsHtml .

14. Archivo .env

WP_ENV=local
WP_HOST=0.0.0.0
WP_PORT=8081
WP_URL=http://192.168.222.40:8081

DB_NAME=paty.wordpress
DB_USER=paty.wordpress
DB_PASSWORD=paty.wordpress
DB_HOST=192.168.222.20
DB_PREFIX=cv_

WP_ADMIN_USER=pflores
WP_ADMIN_PASSWORD=HXk4boxuI1QYum3jKL

15. Configuración wp-config.php clave

// Auto-updates DESACTIVADAS (protege archivos de temas y plugins locales)
define('AUTOMATIC_UPDATER_DISABLED', true);
define('WP_AUTO_UPDATE_CORE', false);

// URL dinámica — funciona con cualquier IP o dominio, y detrás de proxy SSL (NPM)
$_wpIsHttps = /* detecta X-Forwarded-Proto: https */;
define('WP_HOME',    $_wpProto . '://' . $_wpHost);
define('WP_SITEURL', $_wpProto . '://' . $_wpHost);

16. Convenciones de código

Elemento Convención
PHP declare(strict_types=1) en todos los archivos
Funciones WordPress Usar esc_html(), esc_url(), esc_attr() en toda salida HTML
Prefijos Funciones y opciones siempre con prefijo del plugin/tema para evitar conflictos
Comentarios Solo cuando el "por qué" no es obvio. Sin comentarios de "qué hace"
Serialización PHP en SQL Generar con php -r "echo serialize([...]);" — nunca manual
Auto-updates WP Siempre desactivadas — no tocar wp-config.php en ese bloque

17. Tareas comunes — referencia rápida

Verificar que todo funciona

curl -s http://127.0.0.1:8081/ | grep -c "Patricia Soledad"
# Debe retornar >= 1

Ver el tema activo

mysql -u "paty.wordpress" -p"paty.wordpress" -h 192.168.222.20 "paty.wordpress" --ssl=0 \
  -e "SELECT option_value FROM cv_options WHERE option_name='template';" 2>/dev/null

Ver todos los datos del CV en BD

mysql -u "paty.wordpress" -p"paty.wordpress" -h 192.168.222.20 "paty.wordpress" --ssl=0 \
  -e "SELECT option_name, LENGTH(option_value) as bytes FROM cv_options WHERE option_name LIKE 'pflores_%' ORDER BY option_name;" 2>/dev/null

Limpiar caché de WordPress (transients)

mysql -u "paty.wordpress" -p"paty.wordpress" -h 192.168.222.20 "paty.wordpress" --ssl=0 \
  -e "DELETE FROM cv_options WHERE option_name LIKE '_site_transient_%' OR option_name LIKE '_transient_%';" 2>/dev/null

Verificar los 4 temas en un loop

for slug in persona-cv lumina apex-cv cvolio; do
  mysql -u "paty.wordpress" -p"paty.wordpress" -h 192.168.222.20 "paty.wordpress" --ssl=0 \
    -e "UPDATE cv_options SET option_value='$slug' WHERE option_name IN('template','stylesheet');" 2>/dev/null
  sleep 0.4
  count=$(curl -s http://127.0.0.1:8081/ | grep -c "Patricia Soledad" || true)
  echo "[$slug] Patricia aparece: $count veces"
done
# Restaurar:
mysql ... -e "UPDATE cv_options SET option_value='persona-cv' WHERE option_name IN('template','stylesheet');"

Probar la descarga del PDF

curl -sI http://127.0.0.1:8081/?cv_pdf=1 | grep -E "Content-Type|Content-Disposition"
# Debe mostrar: application/pdf y attachment; filename="CV_Patricia_Flores_Sanchez.pdf"

Comprobar PHP syntax de un tema

php -l /ruta/al/tema/front-page.php
php -l /ruta/al/tema/functions.php

18. Errores frecuentes y soluciones

Error Causa probable Solución
Página en blanco o "error crítico" PHP fatal en el tema Ver debug.log, buscar la línea del error
CSS sin cargar / página sin estilos Mixed content (HTTP vs HTTPS) Verificar wp-config.php — bloque de proxy SSL
CMB2 / plugin no carga Serialización incorrecta en active_plugins Regenerar con php -r "echo serialize([...]);"
pflores_get_cv_data() retorna vacío Datos no guardados en BD Re-ejecutar populate-data.php?key=pflores2024 + limpiar caché
Apex-cv vacío o sin archivos Tema apex-cv depende de directorio real, no symlink Los archivos van en wp-content/themes/apex-cv/, no en frontend/
PDF vacío o error 500 Chromium no encontrado o falla which chromium chromium-browser google-chrome
update_option no guarda Caché de WordPress Limpiar transients (ver sección 17)

19. Acerca de los temas — resumen visual

Tema Estilo Layout Fuente Acento
persona-cv Personage/Pixflow, secciones alternas Full-width, nav sticky top Raleway + Open Sans Rojo #c0392b
lumina Claro, moderno, alegre Sidebar IZQUIERDO fijo Plus Jakarta Sans Teal #0d9488 + Ámbar
apex-cv Oscuro, serio, editorial Sidebar IZQUIERDO fijo Space Grotesk Cian #22d3ee + Dorado
cvolio Oscuro glassmorphism Hero dividido + sidebar DERECHO Manrope + Cormorant Café/tostado

20. Notas importantes para la IA asistente

  1. No usar ACF (Advanced Custom Fields). Tiene Repeater solo en versión de pago. Usar CMB2.
  2. No instalar plugins de pago. Todo debe ser 100 % gratuito.
  3. No tocar el bloque de auto-updates en wp-config.php.
  4. Verificar serialización PHP antes de cualquier UPDATE en active_plugins o similar.
  5. Limpiar caché después de modificar datos en BD directamente.
  6. La foto de perfil es assets/images/patricia-flores-profile.jpeg en cada tema — NO usar el placeholder SVG como defecto.
  7. El CV en docx (CV_Patricia_Flores_Sanchez_ES_FINAL.docx) es solo para descarga — el contenido de la web se gestiona por CMB2.
  8. El PDF se genera dinámicamente con Chromium desde /?cv_pdf=1 — no hay PDF estático.
  9. Los 4 temas leen de CMB2 mediante pflores_get_cv_data(). Si esa función no existe (plugin inactivo), cada tema usa su propio fallback hardcodeado.
  10. Siempre verificar con curl -s http://127.0.0.1:8081/ | grep -c "Patricia Soledad" que el sitio responde correctamente después de cualquier cambio.

21. Git y Gitea — versionar y subir

Repositorio

  • Remoto: https://gitea.linkedcorp.net/mgonzalez/pflores.linkedcorp.net.git
  • Rama: main
  • Credenciales: archivo local .token_gitea (nunca versionado)

Flujo estándar de commit + push

# 1. Revisar qué cambió
git status
git diff --stat

# 2. Agregar archivos — SELECTIVO (nunca git add -A sin revisar)
git add frontend/         # temas propios
git add backend/wordpress/wp-content/plugins/pflores-cv-fields/
git add backend/wordpress/wp-content/themes/apex-cv/
git add backend/wordpress/wp-config.php
git add CHANGELOG.md VERSION README.md PROMPT_IA.md

# 3. Confirmar que .env y .token_gitea NO están en staging
git status | grep -E "\.env|\.token"   # debe retornar vacío

# 4. Commit
git commit -m "tipo: descripción corta"
# Prefijos: feat: / fix: / docs: / chore: / style:

# 5. Push
git push origin main

Credenciales para push

Al hacer git push por primera vez pedirá usuario y contraseña:

  • Usuario: mgonzalez
  • Contraseña: Personal Access Token (NO la contraseña web de Gitea)

Crear token: https://gitea.linkedcorp.net/user/settings/applications

Para no escribir credenciales cada vez:

git config credential.helper store
# La primera vez las guarda; las siguientes son automáticas

Guardar también en .token_gitea (local, nunca versionar):

# Token gitea
usuario: mgonzalez
token: [token de gitea.linkedcorp.net]

Qué SE versiona vs qué NO

SE versiona:

  • frontend/ (todos los temas propios)
  • backend/wordpress/wp-content/plugins/pflores-cv-fields/
  • backend/wordpress/wp-content/themes/apex-cv/
  • backend/wordpress/wp-config.php
  • backend/start-wordpress.sh, docs/, *.md, VERSION
  • CV_Patricia_Flores_Sanchez_ES_FINAL.docx, imágenes del CV

NO se versiona:

  • .env, .token_gitea, LOCAL_DEPLOY_CONTEXT.md
  • WordPress core (wp-admin/, wp-includes/)
  • Plugins de terceros (cmb2/, wp-mail-smtp/)
  • Temas por defecto de WP (twenty*/)
  • wp-content/debug.log, uploads/, languages/

Versionar antes de hacer push

Ver VERSIONADO.md para decidir si subir X, Y o Z:

# Actualizar VERSION
echo "1.0.1" > VERSION

# Anotar cambio en CHANGELOG.md
# Luego commit y push normal