Desarrollo web
El migrador ya habla con el WordPress de producción
Primer piloto contra el WordPress real: autenticación dual, prefijos de tablas, catálogos de comarcas y HTML de Gutenberg convertido a Lexical.

Llevo tres semanas con el migrador trabajando sobre datos de prueba. Hoy lo he puesto delante del WordPress real: la base de datos de producción, con sus prefijos rarísimos y las taxonomías de Toolset. La fase 3 ya no es un borrador: el piloto importa.
Dos puertas para entrar en Payload
El primer problema ni siquiera era de migración: era de autenticación. El plugin de API keys de Payload pide configuración manual desde la interfaz, y yo quería un camino que funcionara siempre. Solución: modo doble. Si hay PAYLOAD_API_KEY, se usa API key; si no, login con email y contraseña (JWT), que funciona out-of-the-box. Y si no hay nada de nada, el script se para con un RuntimeError que lo explica.
Encontrar las tablas buenas
Para detectar el prefijo de las tablas WordPress hacía un LIKE '%\_posts'. PyMySQL se lo come como un especificador de formato, y además el primer candidato que salía era una tabla de Mailpoet, no del core. Dos correcciones: escapar el porcentaje (%%) y cruzar con las tablas *_options, que son las que delatan el core de WordPress. Si hay varias candidatas, gana el prefijo más corto.
Comarcas, municipios y detalles que no perdonan
En el primer pilot nada enlazaba: las comarcas no se resolvían a IDs, el seed decía berguedà con acento y el WordPress lo tiene sin él, y Payload quería enteros donde le pasaba strings. Ahora los catálogos de comarcas y municipios se crean solos (idempotentes) y las relaciones van con el tipo correcto. Para Bagà han salido 13 posts: 1 de cultura y 12 eventos del calendario.
De HTML de Gutenberg a Lexical
El contenido del WP llegaba con comentarios <!-- wp:paragraph --> que Payload escapaba y mostraba literalmente en la página. He reescrito el conversor con html.parser: limpia los comentarios de Gutenberg, mapea párrafos, encabezados y listas, y conserva negritas y cursivas dentro del texto. Los enlaces, además, pedían campos extra en el nodo (id, direction, format): sin ellos, el admin petaba con un React error #418 y escondía todos los campos richText. Con el parser nuevo, las dos piezas del último piloto se ven limpias en el frontend.
De paso: dependencias al día
He aprovechado para poner Payload 3.89, Next 15.4.11 y React 19.0.1: el peer dep de Payload lo exigía. El error #418 ha sobrevivido a la actualización, que era otra pista de que era estructural y no de versión.
Balance del día: 29 smoke tests en verde, dos pilotos importados con portada y meta descripción, y la sensación de que la fase 3 por fin camina sola.