<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Fran Moreno | Blog</title><description>El Blog de Fran Moreno</description><link>https://franmoreno.com/</link><language>es-es</language><item><title>Workers AI no compite con OpenAI: compite por un sitio en tu arquitectura</title><link>https://franmoreno.com/blog/workers-ai-cloudflare-evaluacion-arquitectura/</link><guid isPermaLink="true">https://franmoreno.com/blog/workers-ai-cloudflare-evaluacion-arquitectura/</guid><pubDate>Wed, 29 Apr 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Cada vez que aparece una comparativa de &quot;Cloudflare Workers AI vs OpenAI&quot; en mi feed, la abro con curiosidad y la cierro a los dos minutos. Casi todas cometen el mismo error de marco: tratar a Workers AI como si fuera un sustituto del último modelo frontier de turno. Comparan Llama 3.1 8B con GPT-4 o Claude Opus, concluyen que pierde por goleada, y dan por zanjada la decisión.&lt;/p&gt;
&lt;p&gt;Llevo un tiempo construyendo aplicaciones que combinan Workers AI con APIs de Anthropic y OpenAI, mi conclusión: &lt;strong&gt;Workers AI no viene a ocupar el sitio de Claude o GPT en tu arquitectura. Viene a ocupar uno distinto.&lt;/strong&gt; Este post es el resultado de pelearme con esa pregunta en proyectos reales y entender qué hace bien, qué hace mal, y dónde tiene sentido meterlo.&lt;/p&gt;
&lt;h2&gt;Qué es Workers AI arquitectónicamente&lt;/h2&gt;
&lt;p&gt;Antes de entrar en modelos y precios, conviene fijar el modelo mental, porque es lo que hace que toda la decisión cuadre.&lt;/p&gt;
&lt;p&gt;Workers AI es &lt;strong&gt;inferencia serverless sobre GPUs distribuidas en la red global de Cloudflare&lt;/strong&gt;. No es un endpoint REST que vive en un único datacenter de Virginia al que tú llamas desde la otra punta del mundo. Es el mismo principio que ya describí cuando hablé de &lt;a href=&quot;/blog/introduccion-a-cloudflare-workers/&quot;&gt;Cloudflare Workers&lt;/a&gt;: tu código se ejecuta cerca del usuario. Solo que aquí lo que ejecutas es un modelo de IA.&lt;/p&gt;
&lt;p&gt;Desde dentro de un Worker, llamar al modelo es literalmente esto:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const respuesta = await env.AI.run(&apos;@cf/meta/llama-3.1-8b-instruct&apos;, {
  prompt: &apos;Tu prompt aquí&apos;
})
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Ni claves de terceros, ni gestión de endpoints, ni SDKs externos, ni preocupación por desde qué región sale la petición. Está integrado en el runtime que ya estás usando.&lt;/p&gt;
&lt;p&gt;La unidad de facturación tiene su propia jerga: &lt;strong&gt;Neurons&lt;/strong&gt;. Workers AI cuesta 0,011 dólares por cada 1.000 Neurons, con una asignación gratuita de 10.000 Neurons al día. Cada modelo consume Neurons a una tasa distinta según su coste computacional, y Cloudflare publica equivalencias por modelo en tokens y en imágenes, así que en la práctica puedes razonar en las unidades a las que estás acostumbrado y el sistema hace la conversión por detrás.&lt;/p&gt;
&lt;p&gt;Lo importante: el coste se mide en GPU compute, no en tokens directamente. Esto es coherente con el hecho de que están hospedando los modelos en su infraestructura, no revendiendo tokens de un proveedor externo.&lt;/p&gt;
&lt;h2&gt;El catálogo es más amplio de lo que parece&lt;/h2&gt;
&lt;p&gt;Otro malentendido frecuente es asumir que Workers AI son &quot;tres Llamas y poco más&quot;. El catálogo lleva tiempo creciendo y conviene mirarlo por tipo de tarea, no por proveedor:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;LLMs generalistas&lt;/strong&gt;: Llama 3.1, Mistral, Qwen 1.5, Hermes 2 Pro, Starling. Y un detalle interesante: están los modelos open-weight de OpenAI (&lt;code&gt;gpt-oss-20b&lt;/code&gt;) y Kimi K2.5 con 256k de contexto, multi-turn tool calling y vision. Los catálogos open-weight ya no son lo que eran hace un año.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Embeddings y reranking&lt;/strong&gt;: la familia &lt;code&gt;bge&lt;/code&gt; (incluyendo &lt;code&gt;bge-reranker-base&lt;/code&gt;). Aquí Workers AI es brutalmente competitivo en precio.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Audio&lt;/strong&gt;: Whisper para STT, Aura para TTS context-aware.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Imagen&lt;/strong&gt;: FLUX.2 (klein y dev) de Black Forest Labs, Lucid Origin y Phoenix de Leonardo.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Guardrails&lt;/strong&gt;: Llama Guard 3 8B, integrado además directamente con AI Gateway.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Especializados&lt;/strong&gt;: traducción multilingüe (m2m100, IndicTrans2), clasificación con DistilBERT, captioning visual con UForm-Gen.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;El mensaje aquí es importante: el catálogo está pensado para &lt;strong&gt;componer aplicaciones de IA&lt;/strong&gt;, no solo para hacer chat. Esto cambia bastante la conversación.&lt;/p&gt;
&lt;h2&gt;El ecosistema es la verdadera ventaja&lt;/h2&gt;
&lt;p&gt;Si Workers AI fuera solo un endpoint donde llamar a Llama, el caso de uso sería estrecho. Lo que lo hace interesante es lo que tiene alrededor.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;AI Gateway&lt;/strong&gt; es la pieza central. Te permite poner un proxy delante de cualquier proveedor de IA (Workers AI, OpenAI, Anthropic, Mistral, Google) con caching, rate limiting, observabilidad, retries, fallback entre proveedores y métricas unificadas. La novedad de 2026 es la &lt;strong&gt;facturación unificada&lt;/strong&gt;: puedes pagar el consumo de OpenAI o Anthropic dentro de tu factura de Cloudflare, sumándole una pequeña comisión. No es un cambio enorme, pero simplifica la vida del que tiene varios proveedores facturando por separado.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Vectorize&lt;/strong&gt; es la base de datos vectorial nativa de Cloudflare. Si vas a generar embeddings con Workers AI, mantenerlos en Vectorize evita salir del ecosistema.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;AI Search&lt;/strong&gt; apareció en 2026 como una capa nueva con storage, índice vectorial y crawling integrados. Está en open beta, así que su madurez es limitada todavía.&lt;/p&gt;
&lt;p&gt;Y todo esto se compone con &lt;strong&gt;Workers, Durable Objects y Queues&lt;/strong&gt; para construir agentes con estado y pipelines asíncronos. Suena obvio cuando lo escribes, pero en la práctica significa que puedes llevarte el 100% de una aplicación de IA a Cloudflare sin dependencias externas. Yo ya conté en su momento por qué he ido &lt;a href=&quot;/blog/moviendo-mis-side-projects-a-cloudflare/&quot;&gt;moviendo mis side projects a Cloudflare&lt;/a&gt; y este punto pesa cada vez más.&lt;/p&gt;
&lt;h2&gt;Cuándo Workers AI es la respuesta correcta&lt;/h2&gt;
&lt;p&gt;Vamos al grano con las decisiones reales. Para mí, Workers AI gana cuando se cumplen varios de estos requisitos a la vez:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;La tarea es &lt;strong&gt;acotada&lt;/strong&gt;: clasificar, extraer tags, generar texto corto, hacer embeddings, moderar, traducir. Cosas donde un Llama 3.1 8B o un Mistral basta y sobra.&lt;/li&gt;
&lt;li&gt;El &lt;strong&gt;volumen&lt;/strong&gt; es alto y el coste por operación importa.&lt;/li&gt;
&lt;li&gt;La &lt;strong&gt;latencia&lt;/strong&gt; importa de verdad: estás sirviendo a usuarios en tiempo real y el round trip a &lt;code&gt;api.openai.com&lt;/code&gt; se nota.&lt;/li&gt;
&lt;li&gt;La &lt;strong&gt;tolerancia a un fallo puntual&lt;/strong&gt; es razonable: si la salida no es perfecta, el usuario corrige o el sistema reintenta.&lt;/li&gt;
&lt;li&gt;Quieres que &lt;strong&gt;los datos no salgan de Cloudflare&lt;/strong&gt; por privacidad o por reducir vendor sprawl.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Un ejemplo concreto que tengo en producción: en &lt;strong&gt;PokerReads&lt;/strong&gt;, uno de mis side projects, hay una funcionalidad de notas sobre jugadores. La idea es que durante una partida puedas escribir desde el móvil una observación rápida sobre alguien (&quot;muy loose en early position&quot;, &quot;no defiende blinds&quot;, &quot;siempre 3betea con AK suited&quot;) y el sistema te devuelva una versión estructurada y un conjunto de tags para categorizar a ese jugador.&lt;/p&gt;
&lt;p&gt;Es exactamente el caso de uso que Workers AI resuelve mejor que cualquier API frontier:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Latencia&lt;/strong&gt;: estoy en mitad de una mano, no quiero esperar segundos. Workers AI ejecutándose en el edge me da respuestas rapidísimas.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Tarea cerrada&lt;/strong&gt;: el vocabulario de tags es relativamente acotado, la estructura de la nota también. No necesito el razonamiento de Claude Opus para esto.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Volumen&lt;/strong&gt;: una nota por mano interesante, varias por sesión, multiplicado por usuarios. Mandarlo todo a Anthropic sería tirar dinero.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Privacidad&lt;/strong&gt;: las notas son observaciones privadas sobre otros jugadores, prefiero que vivan dentro de Cloudflare.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Coste de error bajo&lt;/strong&gt;: si un tag no acaba de encajar, el usuario lo corrige en dos toques.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Llamar a Claude o GPT para esto sería sobrecualificación pura. Un Llama 3.1 8B con un prompt bien afinado hace exactamente lo que necesito y a un coste residual.&lt;/p&gt;
&lt;h2&gt;Cuándo Workers AI no es la respuesta&lt;/h2&gt;
&lt;p&gt;Ahora el contrapunto, que es donde la mayoría de posts se quedan cortos.&lt;/p&gt;
&lt;p&gt;Workers AI pierde claramente cuando:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;La tarea requiere &lt;strong&gt;razonamiento complejo, multi-paso o tool use sofisticado&lt;/strong&gt;. Aquí Claude y GPT siguen estando varias categorías por encima.&lt;/li&gt;
&lt;li&gt;Necesitas &lt;strong&gt;vision capabilities&lt;/strong&gt; serias sobre layouts variables o documentos complejos.&lt;/li&gt;
&lt;li&gt;Trabajas con &lt;strong&gt;contexto realmente largo y necesitas buen recall&lt;/strong&gt; dentro de él. Aunque Kimi K2.5 trae 256k de contexto, los frontier models siguen ganando en cómo aprovechan ese contexto.&lt;/li&gt;
&lt;li&gt;El &lt;strong&gt;coste de un mal output es alto&lt;/strong&gt;. Si un fallo en la extracción llega al cliente final, ahorrar unos céntimos no compensa.&lt;/li&gt;
&lt;li&gt;Quieres &lt;strong&gt;lo último&lt;/strong&gt;. Workers AI suele ir por detrás del estado del arte, lógicamente.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Aquí entra mi otro proyecto, el &lt;strong&gt;SaaS de gestión para hostelería&lt;/strong&gt; del que ya he hablado en &lt;a href=&quot;/blog/3-herramientas-desarrollo-fullstack-2025/&quot;&gt;otros posts&lt;/a&gt;. Una de las funcionalidades clave es la extracción de datos desde documentos: facturas de proveedores, menús, listas de precios. El usuario sube un PDF o una foto y el sistema tiene que extraer items, precios, IVA, alérgenos, lo que aplique según el documento.&lt;/p&gt;
&lt;p&gt;Aquí elegí &lt;strong&gt;la API de Anthropic con Claude&lt;/strong&gt; sin pensármelo dos veces:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Vision capabilities&lt;/strong&gt;: Claude lee documentos con layouts variables (cada proveedor factura distinto) con una precisión que los modelos disponibles en Workers AI no alcanzan.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Razonamiento sobre estructura&lt;/strong&gt;: identificar qué es una línea de producto, qué es un total, qué es un descuento, requiere razonar sobre el documento, no solo extraer texto.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Coste de error alto&lt;/strong&gt;: estos datos van a la contabilidad del cliente. Un campo mal extraído es una incidencia, una llamada de soporte y, potencialmente, un cliente perdido.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Volumen moderado&lt;/strong&gt;: una factura no se procesa en cada interacción del usuario. El coste por operación pesa menos que la fiabilidad.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Si intentara hacer esto con Workers AI, me ahorraría dinero por documento procesado, pero me lo gastaría con creces en horas de soporte y en pérdida de confianza. La cuenta sale al revés.&lt;/p&gt;
&lt;h2&gt;El patrón ganador es híbrido&lt;/h2&gt;
&lt;p&gt;La conclusión práctica de todo esto es que la pregunta correcta no es &quot;¿Workers AI o Anthropic?&quot;. Es &quot;¿qué pieza de mi arquitectura hace cada cosa?&quot;.&lt;/p&gt;
&lt;p&gt;El patrón que estoy viendo funcionar en proyectos reales es híbrido:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Workers AI&lt;/strong&gt; para preprocesamiento, embeddings, clasificación, moderación, primera línea, tareas auxiliares de alto volumen.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Frontier models (Anthropic, OpenAI)&lt;/strong&gt; para el razonamiento donde la calidad importa de verdad: extracción compleja, agentes, generación con altos estándares de calidad.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;AI Gateway&lt;/strong&gt; como capa unificada por delante de todo: caching, observabilidad, fallback, control de costes.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Resumido en mis dos proyectos:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;PokerReads&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;SaaS hostelería&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Tarea&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Estructurar notas y tagging&lt;/td&gt;
&lt;td&gt;Extracción de datos de documentos&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Modelo elegido&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Workers AI (Llama 3.1)&lt;/td&gt;
&lt;td&gt;Anthropic (Claude)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Razón principal&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Latencia + volumen + coste&lt;/td&gt;
&lt;td&gt;Precisión + razonamiento + vision&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Coste de error&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Bajo (el usuario corrige)&lt;/td&gt;
&lt;td&gt;Alto (datos del cliente)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Contexto de uso&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Móvil, en vivo&lt;/td&gt;
&lt;td&gt;Backend, asíncrono&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Esta tabla es más útil que cualquier benchmark, porque reproduce el tipo de decisión que tomas tú cuando arrancas un proyecto.&lt;/p&gt;
&lt;p&gt;En un próximo post quiero entrar al detalle del patrón híbrido con código: cómo enrutar peticiones entre Workers AI y Anthropic con AI Gateway, cómo aplicar fallback cuando una llamada falla, y cómo medir si la decisión inicial era correcta o conviene cambiarla. Aviso aquí cuando esté.&lt;/p&gt;
&lt;h2&gt;Limitaciones que hay que reconocer&lt;/h2&gt;
&lt;p&gt;Para no cerrar con un tono comercial, lo que conviene tener presente antes de meterse de cabeza:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Los modelos en Workers AI &lt;strong&gt;van por detrás del estado del arte&lt;/strong&gt;. No esperes encontrar Claude Opus o el último GPT aquí. Esto no va a cambiar.&lt;/li&gt;
&lt;li&gt;Hay &lt;strong&gt;rate limits por modelo&lt;/strong&gt; que pueden sorprenderte en producción. Conviene revisarlos antes de diseñar pipelines de alto volumen.&lt;/li&gt;
&lt;li&gt;Algunos modelos están &lt;strong&gt;en beta&lt;/strong&gt; y la calidad varía entre versiones. Los más nuevos pueden tener comportamientos inesperados con prompts que ya tenías afinados.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;El catálogo cambia rápido&lt;/strong&gt;. Lo que escribo hoy puede haber envejecido en seis meses. Es algo a chequear de tanto en tanto.&lt;/li&gt;
&lt;li&gt;AI Search y otras piezas del ecosistema están &lt;strong&gt;todavía evolucionando&lt;/strong&gt;. Para producción crítica, conviene tomarlas con prudencia.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Cierre&lt;/h2&gt;
&lt;p&gt;La conclusión la he ido repitiendo a propósito porque es el mensaje que quería que se llevara el lector: &lt;strong&gt;Workers AI no compite con Anthropic ni OpenAI&lt;/strong&gt;. Resuelve un problema distinto: hacer inferencia barata, rápida y cerca del usuario para tareas donde no necesitas el último frontier model.&lt;/p&gt;
&lt;p&gt;Si te lo planteas como un sustituto, sales decepcionado. Si te lo planteas como una pieza más de tu arquitectura, lo combinas con frontier models a través de AI Gateway, y eliges qué tarea va a cada sitio según latencia, coste, calidad requerida y privacidad, descubres que el stack es bastante más potente que cualquiera de las piezas por separado.&lt;/p&gt;
&lt;p&gt;En mi caso, llevar tareas auxiliares a Workers AI y reservar Anthropic para lo que de verdad lo necesita ha bajado el coste de mis side projects significativamente sin sacrificar calidad donde importa. Y, para mantener todo el stack en un mismo proveedor, encaja con la dirección que llevo tiempo siguiendo de &lt;a href=&quot;/blog/moviendo-mis-side-projects-a-cloudflare/&quot;&gt;moverlo todo a Cloudflare&lt;/a&gt;.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;🚀 ¿Empezando un proyecto en Cloudflare?&lt;/strong&gt; Si quieres saltarte la parte de fontanería (auth, base de datos, CI/CD) y centrarte en construir tu producto sobre Workers/Pages, el &lt;a href=&quot;https://fransiner.gumroad.com/l/nextjs-cloudflare-starter-auth-database-edge-deploy&quot;&gt;&lt;strong&gt;Next.js + Cloudflare Pages Starter Kit&lt;/strong&gt;&lt;/a&gt; trae Better Auth, Drizzle + Supabase y deploy automático listos. La base perfecta para sumarle Workers AI por encima.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;¿Estás usando Workers AI en algún proyecto? ¿Lo combinas con OpenAI o Anthropic? Me interesa especialmente cómo estás enrutando entre proveedores y si has dado con algún patrón que te esté funcionando. Cuéntame.&lt;/p&gt;
</content:encoded></item><item><title>Desplegando una App Next.js (App Router) con Server Actions en Cloudflare Pages (Funciones Incluidas)</title><link>https://franmoreno.com/blog/desplegando-nextjs-app-router-server-actions-cloudflare-pages/</link><guid isPermaLink="true">https://franmoreno.com/blog/desplegando-nextjs-app-router-server-actions-cloudflare-pages/</guid><pubDate>Fri, 03 Oct 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Si has seguido la evolución de &lt;a href=&quot;https://nextjs.org/&quot;&gt;Next.js&lt;/a&gt; y has experimentado con el nuevo &lt;a href=&quot;https://nextjs.org/docs/app&quot;&gt;App Router&lt;/a&gt;, seguramente te has topado con las &lt;a href=&quot;https://nextjs.org/docs/app/building-your-application/data-fetching/server-actions-and-mutations&quot;&gt;Server Actions&lt;/a&gt;. Son una característica potente que permite ejecutar código del servidor directamente desde componentes cliente, simplificando enormemente el manejo de formularios y mutaciones de datos.&lt;/p&gt;
&lt;p&gt;Hasta hace poco, desplegar aplicaciones Next.js con estas características modernas en &lt;a href=&quot;https://pages.cloudflare.com/&quot;&gt;Cloudflare Pages&lt;/a&gt; era complicado o directamente imposible. Sin embargo, con las últimas mejoras en el soporte de Cloudflare para Next.js y las funciones serverless, ahora es posible y sorprendentemente sencillo.&lt;/p&gt;
&lt;p&gt;En este tutorial te muestro paso a paso cómo desplegar una aplicación Next.js completa con App Router y Server Actions en Cloudflare Pages, aprovechando al máximo la infraestructura global de Cloudflare.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;💡 Repositorio Demo&lt;/strong&gt;: Puedes acceder al código completo de este tutorial en GitHub: &lt;a href=&quot;https://github.com/siner/nextjs-cloudflare-demo&quot;&gt;nextjs-cloudflare-demo&lt;/a&gt;. El repositorio incluye toda la configuración y código necesario para seguir el tutorial.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;🚀 ¿Quieres saltarte la configuración?&lt;/strong&gt; Si prefieres empezar directamente con un proyecto listo para producción —con autenticación (Better Auth), base de datos (Drizzle + Supabase), CI/CD con GitHub Actions y deploy automático en Cloudflare Pages— echa un vistazo al &lt;a href=&quot;/productos/#productos&quot;&gt;&lt;strong&gt;Next.js + Cloudflare Pages Starter Kit&lt;/strong&gt;&lt;/a&gt;. De cero a desplegado en ~30 minutos.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;¿Por qué Cloudflare Pages para Next.js?&lt;/h2&gt;
&lt;p&gt;Antes de saltar al tutorial, déjame explicarte por qué considero que Cloudflare Pages es una excelente opción para alojar aplicaciones Next.js en 2025:&lt;/p&gt;
&lt;h3&gt;Ventajas de Cloudflare Pages&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Red Global&lt;/strong&gt;: Más de 275+ ubicaciones en todo el mundo significa que tu aplicación estará cerca de tus usuarios.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Funciones Serverless Incluidas&lt;/strong&gt;: Soporte nativo para Server Actions y API Routes sin configuración adicional.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Precios Competitivos&lt;/strong&gt;: Plan gratuito muy generoso, ideal para proyectos personales y startups.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Rendimiento Excelente&lt;/strong&gt;: CDN integrado y optimizaciones automáticas.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Facilidad de Despliegue&lt;/strong&gt;: Integración directa con GitHub y GitLab.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Como mencioné en mi &lt;a href=&quot;/blog/moviendo-mis-side-projects-a-cloudflare/&quot;&gt;experiencia moviendo proyectos a Cloudflare&lt;/a&gt;, he tenido muy buenas experiencias con su plataforma, especialmente en términos de rendimiento y costos.&lt;/p&gt;
&lt;h2&gt;Requisitos Previos&lt;/h2&gt;
&lt;p&gt;Para seguir este tutorial, necesitarás:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Node.js 18+ instalado&lt;/li&gt;
&lt;li&gt;Una cuenta en &lt;a href=&quot;https://cloudflare.com&quot;&gt;Cloudflare&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Una cuenta en GitHub (para el despliegue automático)&lt;/li&gt;
&lt;li&gt;Conocimientos básicos de React y Next.js&lt;/li&gt;
&lt;li&gt;Familiaridad con el App Router de Next.js&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Paso 1: Creando la Aplicación Next.js de Ejemplo&lt;/h2&gt;
&lt;p&gt;Tienes dos opciones para seguir este tutorial:&lt;/p&gt;
&lt;h3&gt;Opción A: Clonar el Repositorio Demo (Recomendado)&lt;/h3&gt;
&lt;p&gt;Si quieres empezar directamente con el código completo:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;git clone https://github.com/siner/nextjs-cloudflare-demo.git
cd nextjs-cloudflare-demo
npm install
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Opción B: Crear la Aplicación desde Cero&lt;/h3&gt;
&lt;p&gt;Vamos a crear una aplicación Next.js desde cero que incluya tanto el App Router como Server Actions. Esta será nuestra aplicación de prueba.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;npx create-next-app@latest nextjs-cloudflare-demo
cd nextjs-cloudflare-demo
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Durante la instalación, asegúrate de seleccionar:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;✅ TypeScript&lt;/li&gt;
&lt;li&gt;✅ ESLint&lt;/li&gt;
&lt;li&gt;✅ Tailwind CSS&lt;/li&gt;
&lt;li&gt;✅ &lt;code&gt;src/&lt;/code&gt; directory&lt;/li&gt;
&lt;li&gt;✅ App Router&lt;/li&gt;
&lt;li&gt;❌ Turbopack (opcional, pero recomendado para desarrollo)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Paso 2: Configurando la Estructura del Proyecto&lt;/h2&gt;
&lt;p&gt;Vamos a crear una aplicación simple con un formulario que utilice Server Actions. Esta demostración incluirá:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Una página principal con un formulario&lt;/li&gt;
&lt;li&gt;Server Actions para manejar el envío del formulario&lt;/li&gt;
&lt;li&gt;Gestión de estado para mostrar mensajes de éxito/error&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;Creando la Página Principal&lt;/h3&gt;
&lt;p&gt;Primero, vamos a modificar &lt;code&gt;src/app/page.tsx&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import { ContactForm } from &apos;@/components/contact-form&apos;
import { Suspense } from &apos;react&apos;

export default function Home() {
  return (
    &amp;lt;main className=&quot;min-h-screen bg-gradient-to-br from-blue-50 to-indigo-100 py-12 px-4&quot;&amp;gt;
      &amp;lt;div className=&quot;max-w-2xl mx-auto&quot;&amp;gt;
        &amp;lt;div className=&quot;text-center mb-12&quot;&amp;gt;
          &amp;lt;h1 className=&quot;text-4xl font-bold text-gray-900 mb-4&quot;&amp;gt;
            Next.js + Cloudflare Pages
          &amp;lt;/h1&amp;gt;
          &amp;lt;p className=&quot;text-xl text-gray-600&quot;&amp;gt;
            Demo de App Router con Server Actions desplegado en Cloudflare Pages
          &amp;lt;/p&amp;gt;
        &amp;lt;/div&amp;gt;

        &amp;lt;div className=&quot;bg-white rounded-lg shadow-lg p-8&quot;&amp;gt;
          &amp;lt;h2 className=&quot;text-2xl font-semibold text-gray-800 mb-6&quot;&amp;gt;
            Formulario de Contacto
          &amp;lt;/h2&amp;gt;
          &amp;lt;Suspense fallback={&amp;lt;div&amp;gt;Cargando formulario...&amp;lt;/div&amp;gt;}&amp;gt;
            &amp;lt;ContactForm /&amp;gt;
          &amp;lt;/Suspense&amp;gt;
        &amp;lt;/div&amp;gt;

        &amp;lt;div className=&quot;mt-8 text-center&quot;&amp;gt;
          &amp;lt;p className=&quot;text-gray-500&quot;&amp;gt;
            Este formulario utiliza Server Actions para procesar los datos
          &amp;lt;/p&amp;gt;
        &amp;lt;/div&amp;gt;
      &amp;lt;/div&amp;gt;
    &amp;lt;/main&amp;gt;
  )
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Creando las Server Actions&lt;/h3&gt;
&lt;p&gt;Ahora vamos a crear nuestras Server Actions. Crea el archivo &lt;code&gt;src/app/actions.ts&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&apos;use server&apos;

import { revalidatePath } from &apos;next/cache&apos;
import { redirect } from &apos;next/navigation&apos;

export type FormState = {
  message: string
  type: &apos;success&apos; | &apos;error&apos; | null
}

export async function submitContactForm(
  prevState: FormState,
  formData: FormData
): Promise&amp;lt;FormState&amp;gt; {
  // Extraer datos del formulario
  const name = formData.get(&apos;name&apos;) as string
  const email = formData.get(&apos;email&apos;) as string
  const message = formData.get(&apos;message&apos;) as string

  // Validación básica
  if (!name || !email || !message) {
    return {
      message: &apos;Todos los campos son obligatorios&apos;,
      type: &apos;error&apos;
    }
  }

  // Validación de email básica
  const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/
  if (!emailRegex.test(email)) {
    return {
      message: &apos;Por favor, introduce un email válido&apos;,
      type: &apos;error&apos;
    }
  }

  try {
    // Simular procesamiento (aquí conectarías con tu base de datos, API externa, etc.)
    await new Promise((resolve) =&amp;gt; setTimeout(resolve, 1000))

    // En un caso real, aquí guardarías en base de datos, enviarías email, etc.
    console.log(&apos;Datos del formulario:&apos;, { name, email, message })

    // Revalidar la página para mostrar los cambios
    revalidatePath(&apos;/&apos;)

    return {
      message: `¡Gracias ${name}! Tu mensaje ha sido enviado correctamente.`,
      type: &apos;success&apos;
    }
  } catch (error) {
    console.error(&apos;Error procesando formulario:&apos;, error)
    return {
      message: &apos;Error interno del servidor. Inténtalo de nuevo.&apos;,
      type: &apos;error&apos;
    }
  }
}

// Server Action alternativa que muestra redirect
export async function submitAndRedirect(formData: FormData) {
  const name = formData.get(&apos;name&apos;) as string

  if (!name) {
    throw new Error(&apos;Nombre es requerido&apos;)
  }

  // Procesar datos...
  await new Promise((resolve) =&amp;gt; setTimeout(resolve, 500))

  // Redirigir a página de éxito
  redirect(`/success?name=${encodeURIComponent(name)}`)
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Creando el Componente del Formulario&lt;/h3&gt;
&lt;p&gt;Crea &lt;code&gt;src/components/contact-form.tsx&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&apos;use client&apos;

import { useFormState, useFormStatus } from &apos;react-dom&apos;
import { submitContactForm, type FormState } from &apos;@/app/actions/contact-form&apos;

const initialState: FormState = {
  message: &apos;&apos;,
  type: null
}

function SubmitButton() {
  const { pending } = useFormStatus()

  return (
    &amp;lt;button
      type=&quot;submit&quot;
      disabled={pending}
      className=&quot;w-full bg-blue-600 text-white py-3 px-4 rounded-lg hover:bg-blue-700 disabled:opacity-50 disabled:cursor-not-allowed transition-colors duration-200&quot;
    &amp;gt;
      {pending ? (
        &amp;lt;&amp;gt;
          &amp;lt;svg
            className=&quot;animate-spin -ml-1 mr-3 h-5 w-5 text-white inline&quot;
            xmlns=&quot;http://www.w3.org/2000/svg&quot;
            fill=&quot;none&quot;
            viewBox=&quot;0 0 24 24&quot;
          &amp;gt;
            &amp;lt;circle
              className=&quot;opacity-25&quot;
              cx=&quot;12&quot;
              cy=&quot;12&quot;
              r=&quot;10&quot;
              stroke=&quot;currentColor&quot;
              strokeWidth=&quot;4&quot;
            &amp;gt;&amp;lt;/circle&amp;gt;
            &amp;lt;path
              className=&quot;opacity-75&quot;
              fill=&quot;currentColor&quot;
              d=&quot;M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z&quot;
            &amp;gt;&amp;lt;/path&amp;gt;
          &amp;lt;/svg&amp;gt;
          Enviando...
        &amp;lt;/&amp;gt;
      ) : (
        &apos;Enviar Mensaje&apos;
      )}
    &amp;lt;/button&amp;gt;
  )
}

export function ContactForm() {
  const [state, formAction] = useFormState(submitContactForm, initialState)

  return (
    &amp;lt;form action={formAction} className=&quot;space-y-6&quot;&amp;gt;
      &amp;lt;div&amp;gt;
        &amp;lt;label
          htmlFor=&quot;name&quot;
          className=&quot;block text-sm font-medium text-gray-700 mb-2&quot;
        &amp;gt;
          Nombre completo
        &amp;lt;/label&amp;gt;
        &amp;lt;input
          type=&quot;text&quot;
          id=&quot;name&quot;
          name=&quot;name&quot;
          required
          className=&quot;w-full px-3 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent&quot;
          placeholder=&quot;Tu nombre&quot;
        /&amp;gt;
      &amp;lt;/div&amp;gt;

      &amp;lt;div&amp;gt;
        &amp;lt;label
          htmlFor=&quot;email&quot;
          className=&quot;block text-sm font-medium text-gray-700 mb-2&quot;
        &amp;gt;
          Email
        &amp;lt;/label&amp;gt;
        &amp;lt;input
          type=&quot;email&quot;
          id=&quot;email&quot;
          name=&quot;email&quot;
          required
          className=&quot;w-full px-3 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent&quot;
          placeholder=&quot;tu@email.com&quot;
        /&amp;gt;
      &amp;lt;/div&amp;gt;

      &amp;lt;div&amp;gt;
        &amp;lt;label
          htmlFor=&quot;message&quot;
          className=&quot;block text-sm font-medium text-gray-700 mb-2&quot;
        &amp;gt;
          Mensaje
        &amp;lt;/label&amp;gt;
        &amp;lt;textarea
          id=&quot;message&quot;
          name=&quot;message&quot;
          rows={4}
          required
          className=&quot;w-full px-3 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent resize-none&quot;
          placeholder=&quot;Escribe tu mensaje aquí...&quot;
        /&amp;gt;
      &amp;lt;/div&amp;gt;

      &amp;lt;SubmitButton /&amp;gt;

      {state.message &amp;amp;&amp;amp; (
        &amp;lt;div
          className={`p-4 rounded-lg ${
            state.type === &apos;success&apos;
              ? &apos;bg-green-50 text-green-800 border border-green-200&apos;
              : &apos;bg-red-50 text-red-800 border border-red-200&apos;
          }`}
        &amp;gt;
          &amp;lt;p className=&quot;text-sm font-medium&quot;&amp;gt;{state.message}&amp;lt;/p&amp;gt;
        &amp;lt;/div&amp;gt;
      )}
    &amp;lt;/form&amp;gt;
  )
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Creando la Página de Éxito (Opcional)&lt;/h3&gt;
&lt;p&gt;Crea &lt;code&gt;src/app/success/page.tsx&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import Link from &apos;next/link&apos;
import { Suspense } from &apos;react&apos;

function SuccessContent({ searchParams }: { searchParams: { name?: string } }) {
  const name = searchParams.name || &apos;Usuario&apos;

  return (
    &amp;lt;main className=&quot;min-h-screen bg-gradient-to-br from-green-50 to-emerald-100 py-12 px-4&quot;&amp;gt;
      &amp;lt;div className=&quot;max-w-2xl mx-auto text-center&quot;&amp;gt;
        &amp;lt;div className=&quot;bg-white rounded-lg shadow-lg p-8&quot;&amp;gt;
          &amp;lt;div className=&quot;mb-6&quot;&amp;gt;
            &amp;lt;div className=&quot;mx-auto w-16 h-16 bg-green-100 rounded-full flex items-center justify-center mb-4&quot;&amp;gt;
              &amp;lt;svg
                className=&quot;w-8 h-8 text-green-600&quot;
                fill=&quot;none&quot;
                stroke=&quot;currentColor&quot;
                viewBox=&quot;0 0 24 24&quot;
              &amp;gt;
                &amp;lt;path
                  strokeLinecap=&quot;round&quot;
                  strokeLinejoin=&quot;round&quot;
                  strokeWidth={2}
                  d=&quot;M5 13l4 4L19 7&quot;
                /&amp;gt;
              &amp;lt;/svg&amp;gt;
            &amp;lt;/div&amp;gt;
            &amp;lt;h1 className=&quot;text-3xl font-bold text-gray-900 mb-2&quot;&amp;gt;
              ¡Mensaje Enviado!
            &amp;lt;/h1&amp;gt;
            &amp;lt;p className=&quot;text-xl text-gray-600&quot;&amp;gt;
              Gracias {decodeURIComponent(name)}, tu mensaje ha sido procesado
              correctamente.
            &amp;lt;/p&amp;gt;
          &amp;lt;/div&amp;gt;

          &amp;lt;Link
            href=&quot;/&quot;
            className=&quot;inline-block bg-blue-600 text-white py-3 px-6 rounded-lg hover:bg-blue-700 transition-colors duration-200&quot;
          &amp;gt;
            Volver al Inicio
          &amp;lt;/Link&amp;gt;
        &amp;lt;/div&amp;gt;
      &amp;lt;/div&amp;gt;
    &amp;lt;/main&amp;gt;
  )
}

export default async function SuccessPage({
  searchParams
}: {
  searchParams: Promise&amp;lt;{ name?: string }&amp;gt;
}) {
  const params = await searchParams
  return (
    &amp;lt;Suspense fallback={&amp;lt;div&amp;gt;Cargando...&amp;lt;/div&amp;gt;}&amp;gt;
      &amp;lt;SuccessContent searchParams={params} /&amp;gt;
    &amp;lt;/Suspense&amp;gt;
  )
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Paso 3: Configuración para Cloudflare Pages&lt;/h2&gt;
&lt;p&gt;Ahora viene la parte crucial: configurar Next.js para que funcione correctamente en Cloudflare Pages.&lt;/p&gt;
&lt;h3&gt;Instalando el Adaptador de Cloudflare&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;npm install @opennextjs/cloudflare
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Nota&lt;/strong&gt;: &lt;code&gt;@opennextjs/cloudflare&lt;/code&gt; es la herramienta oficial actualizada para desplegar Next.js en Cloudflare Pages. Reemplaza al anterior &lt;code&gt;@cloudflare/next-on-pages&lt;/code&gt; y ofrece mejor soporte para las características modernas de Next.js como Server Actions y el App Router.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;Configurando next.config.js&lt;/h3&gt;
&lt;p&gt;Crea o modifica &lt;code&gt;next.config.js&lt;/code&gt; en la raíz del proyecto:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;/** @type {import(&apos;next&apos;).NextConfig} */
const nextConfig = {
  // Optimizaciones para Cloudflare
  images: {
    unoptimized: true // Cloudflare optimiza las imágenes por defecto
  },

  // Configuración adicional para mejor compatibilidad
  swcMinify: true,

  // Headers de seguridad (opcional pero recomendado)
  async headers() {
    return [
      {
        source: &apos;/(.*)&apos;,
        headers: [
          {
            key: &apos;X-Frame-Options&apos;,
            value: &apos;DENY&apos;
          },
          {
            key: &apos;X-Content-Type-Options&apos;,
            value: &apos;nosniff&apos;
          }
        ]
      }
    ]
  }
}

module.exports = nextConfig
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Configuración de Package.json&lt;/h3&gt;
&lt;p&gt;Actualiza los scripts en tu &lt;code&gt;package.json&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;{
  &quot;scripts&quot;: {
    &quot;dev&quot;: &quot;next dev&quot;,
    &quot;build&quot;: &quot;next build&quot;,
    &quot;start&quot;: &quot;next start&quot;,
    &quot;lint&quot;: &quot;next lint&quot;,
    &quot;pages:build&quot;: &quot;opennextjs-cloudflare build&quot;,
    &quot;preview&quot;: &quot;npm run pages:build &amp;amp;&amp;amp; opennextjs-cloudflare preview&quot;,
    &quot;deploy&quot;: &quot;npm run pages:build &amp;amp;&amp;amp; opennextjs-cloudflare deploy&quot;,
    &quot;cf-typegen&quot;: &quot;wrangler types --env-interface CloudflareEnv cloudflare-env.d.ts&quot;
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Configuración de OpenNext&lt;/h3&gt;
&lt;p&gt;Crea un archivo &lt;code&gt;open-next.config.ts&lt;/code&gt; en la raíz del proyecto:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import { defineCloudflareConfig } from &apos;@opennextjs/cloudflare&apos;

export default defineCloudflareConfig({
  // Configuraciones específicas para tu proyecto
})
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Paso 4: Preparando el Repositorio&lt;/h2&gt;
&lt;h3&gt;Estructura Final del Proyecto&lt;/h3&gt;
&lt;p&gt;Tu proyecto debería tener esta estructura:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;nextjs-cloudflare-demo/
├── src/
│   ├── app/
│   │   ├── actions.ts
│   │   ├── globals.css
│   │   ├── layout.tsx
│   │   ├── page.tsx
│   │   └── success/
│   │       └── page.tsx
│   └── components/
│       └── ContactForm.tsx
├── next.config.js
├── open-next.config.ts
├── package.json
├── tailwind.config.js
└── tsconfig.json
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Archivo .gitignore&lt;/h3&gt;
&lt;p&gt;Asegúrate de que tu &lt;code&gt;.gitignore&lt;/code&gt; incluya:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;# Dependencies
node_modules/

# Next.js
.next/
out/

# OpenNext y Cloudflare
.open-next/
.wrangler/

# Environment variables
.env*.local

# Logs
*.log

# Runtime data
pids
*.pid
*.seed
*.pid.lock
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Commiteando el Código&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;git add .
git commit -m &quot;feat: Aplicación Next.js con App Router y Server Actions para Cloudflare Pages&quot;
git push origin main
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Desarrollo y Previsualización Local&lt;/h2&gt;
&lt;p&gt;Antes de desplegar, es importante probar localmente con el runtime de Cloudflare:&lt;/p&gt;
&lt;h3&gt;Desarrollo Regular&lt;/h3&gt;
&lt;p&gt;Para desarrollo regular, usa el servidor de Next.js:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;npm run dev
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Previsualización con Runtime de Cloudflare&lt;/h3&gt;
&lt;p&gt;Para probar cómo funcionará en producción:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;npm run preview
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Este comando:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Construye tu aplicación con el adaptador de OpenNext&lt;/li&gt;
&lt;li&gt;La sirve localmente usando el runtime de &lt;code&gt;workers&lt;/code&gt; (mismo que usa Cloudflare)&lt;/li&gt;
&lt;li&gt;Te permite probar Server Actions y otras características específicas de Cloudflare&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;Paso 5: Configurando Cloudflare Pages&lt;/h2&gt;
&lt;h3&gt;Creando el Proyecto en Cloudflare Pages&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;Ve a &lt;a href=&quot;https://dash.cloudflare.com&quot;&gt;Cloudflare Dashboard&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Navega a &lt;strong&gt;Pages&lt;/strong&gt; en el menú lateral&lt;/li&gt;
&lt;li&gt;Haz clic en &lt;strong&gt;&quot;Crear Proyecto&quot;&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Selecciona &lt;strong&gt;&quot;Conectar a Git&quot;&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Autoriza a Cloudflare a acceder a tu repositorio de GitHub&lt;/li&gt;
&lt;li&gt;Selecciona tu repositorio &lt;code&gt;nextjs-cloudflare-demo&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;Configuración de Build&lt;/h3&gt;
&lt;p&gt;En la pantalla de configuración de build, usa estos ajustes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Framework preset&lt;/strong&gt;: Next.js&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Build command&lt;/strong&gt;: &lt;code&gt;npm run pages:build&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Build output directory&lt;/strong&gt;: &lt;code&gt;.open-next/assets&lt;/code&gt; (o &lt;code&gt;.open-next&lt;/code&gt; según la configuración)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Root directory&lt;/strong&gt;: &lt;code&gt;/&lt;/code&gt; (raíz del proyecto)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Variables de Entorno (Opcional)&lt;/h3&gt;
&lt;p&gt;Si tu aplicación necesita variables de entorno, puedes agregarlas en la sección &lt;strong&gt;&quot;Variables de Entorno&quot;&lt;/strong&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;NODE_VERSION=18
NEXT_TELEMETRY_DISABLED=1
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Configuración Avanzada&lt;/h3&gt;
&lt;p&gt;En &lt;strong&gt;&quot;Configuración Avanzada&quot;&lt;/strong&gt;, puedes ajustar:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Compatibility flags&lt;/strong&gt;: &lt;code&gt;nodejs_compat&lt;/code&gt; (para Server Actions)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Node.js compatibility&lt;/strong&gt;: Habilitado&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Paso 6: Despliegue y Verificación&lt;/h2&gt;
&lt;h3&gt;Iniciando el Despliegue&lt;/h3&gt;
&lt;p&gt;Haz clic en &lt;strong&gt;&quot;Guardar y Desplegar&quot;&lt;/strong&gt;. Cloudflare comenzará a:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Clonar tu repositorio&lt;/li&gt;
&lt;li&gt;Instalar dependencias (&lt;code&gt;npm install&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Ejecutar el build (&lt;code&gt;npm run pages:build&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Desplegar a la red global de Cloudflare&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;Monitoreando el Progreso&lt;/h3&gt;
&lt;p&gt;Puedes seguir el progreso del despliegue en tiempo real. El proceso típicamente toma 2-5 minutos.&lt;/p&gt;
&lt;h3&gt;Verificando la Funcionalidad&lt;/h3&gt;
&lt;p&gt;Una vez completado el despliegue:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Visita tu sitio&lt;/strong&gt;: Cloudflare te proporcionará una URL (ej: &lt;code&gt;https://nextjs-cloudflare-demo.pages.dev&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Prueba el formulario&lt;/strong&gt;: Completa y envía el formulario de contacto&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Verifica las Server Actions&lt;/strong&gt;: El formulario debería procesarse correctamente en el servidor&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Revisa las funciones&lt;/strong&gt;: En el dashboard de Cloudflare, ve a &lt;strong&gt;Pages &amp;gt; Tu Proyecto &amp;gt; Funciones&lt;/strong&gt; para ver las estadísticas de uso&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;Paso 7: Configuración de Dominio Personalizado (Opcional)&lt;/h2&gt;
&lt;h3&gt;Agregando tu Dominio&lt;/h3&gt;
&lt;p&gt;Si tienes un dominio personalizado:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Ve a &lt;strong&gt;Pages &amp;gt; Tu Proyecto &amp;gt; Configuración&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Haz clic en &lt;strong&gt;&quot;Dominios Personalizados&quot;&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Haz clic en &lt;strong&gt;&quot;Configurar dominio personalizado&quot;&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Introduce tu dominio (ej: &lt;code&gt;mi-app.midominio.com&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Sigue las instrucciones para configurar los registros DNS&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;Configurando SSL&lt;/h3&gt;
&lt;p&gt;Cloudflare proporciona SSL automáticamente. Para dominios personalizados:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Asegúrate de que tu dominio esté gestionado por Cloudflare&lt;/li&gt;
&lt;li&gt;Habilita &lt;strong&gt;&quot;SSL/TLS Encryption Mode: Full&quot;&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Activa &lt;strong&gt;&quot;Always Use HTTPS&quot;&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;Optimizaciones y Mejores Prácticas&lt;/h2&gt;
&lt;h3&gt;Performance&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Caching&lt;/strong&gt;: Cloudflare cachea automáticamente assets estáticos&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Minification&lt;/strong&gt;: Habilitada por defecto para CSS, JS y HTML&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Brotli Compression&lt;/strong&gt;: Automática para mejor compresión&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;Seguridad&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;// next.config.js - Headers de seguridad adicionales
async headers() {
  return [
    {
      source: &apos;/(.*)&apos;,
      headers: [
        {
          key: &apos;Strict-Transport-Security&apos;,
          value: &apos;max-age=31536000; includeSubDomains&apos;
        },
        {
          key: &apos;Content-Security-Policy&apos;,
          value: &quot;default-src &apos;self&apos;; script-src &apos;self&apos; &apos;unsafe-inline&apos; &apos;unsafe-eval&apos;&quot;
        }
      ]
    }
  ]
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Monitoreo&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Analytics&lt;/strong&gt;: Habilita Cloudflare Web Analytics&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Real User Monitoring&lt;/strong&gt;: Para métricas de rendimiento real&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Logs&lt;/strong&gt;: Revisa logs de funciones para debugging&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;Troubleshooting Común&lt;/h2&gt;
&lt;h3&gt;Problemas con Server Actions&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Error&lt;/strong&gt;: &quot;Server Actions not working&quot;
&lt;strong&gt;Solución&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Verifica que &lt;code&gt;nodejs_compat&lt;/code&gt; esté habilitado&lt;/li&gt;
&lt;li&gt;Asegúrate de usar &lt;code&gt;&apos;use server&apos;&lt;/code&gt; al inicio de tus actions&lt;/li&gt;
&lt;li&gt;Revisa los logs de funciones en Cloudflare&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Build Failures&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Error&lt;/strong&gt;: &quot;Build failed&quot;
&lt;strong&gt;Solución&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Verifica que &lt;code&gt;@opennextjs/cloudflare&lt;/code&gt; esté instalado&lt;/li&gt;
&lt;li&gt;Usa Node.js 18+&lt;/li&gt;
&lt;li&gt;Revisa la configuración de &lt;code&gt;next.config.js&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Runtime Errors&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Error&lt;/strong&gt;: &quot;Runtime errors in production&quot;
&lt;strong&gt;Solución&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Revisa los logs de Pages Functions&lt;/li&gt;
&lt;li&gt;Verifica compatibilidad de dependencias con Workers Runtime&lt;/li&gt;
&lt;li&gt;Considera usar polyfills si es necesario&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Limitaciones a Considerar&lt;/h2&gt;
&lt;h3&gt;Compatibilidad del Adaptador OpenNext&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Compatibilidad con Windows&lt;/strong&gt;: Actualmente, &lt;code&gt;@opennextjs/cloudflare&lt;/code&gt; no es totalmente compatible con Windows. Se espera compatibilidad completa en la versión 1.0.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Runtime de Edge&lt;/strong&gt;: El adaptador actualmente solo soporta el runtime de Node.js de Next.js. El soporte para Edge Runtime está planificado para la próxima versión principal.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;Workers Runtime Limitations&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;CPU Time&lt;/strong&gt;: Límite de 30 segundos por request en plan gratuito&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Memory&lt;/strong&gt;: Límite de memoria más restrictivo que Node.js tradicional&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;APIs&lt;/strong&gt;: Algunas APIs de Node.js no están disponibles en el runtime de Workers&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;Next.js Features&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Middleware&lt;/strong&gt;: Soporte limitado, usa Workers en su lugar&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Custom Server&lt;/strong&gt;: No soportado, usa funciones en su lugar&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Incremental Static Regeneration&lt;/strong&gt;: Funcionalidad limitada&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;Conclusión&lt;/h2&gt;
&lt;p&gt;Desplegar Next.js con App Router y Server Actions en Cloudflare Pages usando &lt;code&gt;@opennextjs/cloudflare&lt;/code&gt; es ahora más accesible y robusto que nunca. Este adaptador oficial, desarrollado por OpenNext, ofrece mejor compatibilidad y soporte para las características modernas de Next.js.&lt;/p&gt;
&lt;p&gt;La combinación de la red global de Cloudflare, las funciones serverless integradas y el soporte mejorado para Next.js hace de esta una opción muy atractiva para aplicaciones modernas, especialmente considerando que OpenNext se ha convertido en el estándar para desplegar Next.js en entornos serverless fuera de Vercel.&lt;/p&gt;
&lt;h3&gt;Ventajas Clave&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Rendimiento Global&lt;/strong&gt;: Tu aplicación estará disponible desde +275 ubicaciones&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Costo Efectivo&lt;/strong&gt;: Plan gratuito muy generoso&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Escalabilidad Automática&lt;/strong&gt;: Sin configuración de infraestructura&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Simplicidad&lt;/strong&gt;: Despliegue automático desde Git&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Funciones Incluidas&lt;/strong&gt;: Server Actions funcionan out-of-the-box&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;Próximos Pasos&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Conecta una base de datos (considera &lt;a href=&quot;https://supabase.com/&quot;&gt;Supabase&lt;/a&gt; o &lt;a href=&quot;https://planetscale.com/&quot;&gt;PlanetScale&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Implementa autenticación con &lt;a href=&quot;https://better-auth.com/&quot;&gt;Better Auth&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Agrega análisis con &lt;a href=&quot;https://www.cloudflare.com/web-analytics/&quot;&gt;Cloudflare Analytics&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Explora &lt;a href=&quot;https://workers.cloudflare.com/&quot;&gt;Cloudflare Workers&lt;/a&gt; para lógica adicional&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Código Completo&lt;/h3&gt;
&lt;p&gt;Recuerda que puedes acceder al código completo de este tutorial en el repositorio de GitHub: &lt;a href=&quot;https://github.com/siner/nextjs-cloudflare-demo&quot;&gt;nextjs-cloudflare-demo&lt;/a&gt;. Incluye:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;✅ Configuración completa de OpenNext para Cloudflare&lt;/li&gt;
&lt;li&gt;✅ Aplicación Next.js con App Router y Server Actions&lt;/li&gt;
&lt;li&gt;✅ Formulario de contacto funcional con validación&lt;/li&gt;
&lt;li&gt;✅ Componentes con manejo de estado y loading&lt;/li&gt;
&lt;li&gt;✅ Configuración de despliegue optimizada&lt;/li&gt;
&lt;li&gt;✅ Ejemplos de uso de Suspense y async components&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;¿Quieres ir un paso más allá?&lt;/h3&gt;
&lt;p&gt;Si este tutorial te ha servido y necesitas un punto de partida más completo —con autenticación, base de datos y CI/CD ya integrados— he empaquetado todo lo que aprendí desplegando proyectos reales en el &lt;a href=&quot;https://fransiner.gumroad.com/l/nextjs-cloudflare-starter-auth-database-edge-deploy&quot;&gt;&lt;strong&gt;Next.js + Cloudflare Pages Starter Kit&lt;/strong&gt;&lt;/a&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;🔐 Better Auth con email/password y Google OAuth&lt;/li&gt;
&lt;li&gt;🗄️ Drizzle ORM + Supabase con esquema listo&lt;/li&gt;
&lt;li&gt;🚀 CI/CD con GitHub Actions y deploy automático&lt;/li&gt;
&lt;li&gt;🎨 Dashboard, sidebar y formularios listos con Tailwind&lt;/li&gt;
&lt;li&gt;🛡️ Security headers configurados por defecto&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href=&quot;https://fransiner.gumroad.com/l/nextjs-cloudflare-starter-auth-database-edge-deploy&quot;&gt;Ver el starter en Gumroad →&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;¿Has probado Next.js en Cloudflare Pages? ¿Qué tal ha sido tu experiencia? ¡Me encantaría conocer tus casos de uso y cualquier truco adicional que hayas descubierto!&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Si quieres explorar otras opciones de hosting o comparar con otros stacks, puedes revisar mi &lt;a href=&quot;/blog/3-herramientas-desarrollo-fullstack-2025/&quot;&gt;análisis de herramientas de desarrollo fullstack&lt;/a&gt; o mi &lt;a href=&quot;/blog/experiencia-nextjs-vs-astro-proyectos-personales/&quot;&gt;experiencia personal con Next.js vs Astro&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
</content:encoded></item><item><title>Cómo organizo mi semana como desarrollador (y por qué he creado un kit descargable para ayudarte)</title><link>https://franmoreno.com/blog/como-organizo-mi-semana-desarrollador-kit-gtd/</link><guid isPermaLink="true">https://franmoreno.com/blog/como-organizo-mi-semana-desarrollador-kit-gtd/</guid><pubDate>Wed, 11 Jun 2025 18:30:00 GMT</pubDate><content:encoded>&lt;p&gt;Ser desarrollador hoy en día implica muchas cosas: programar, atender reuniones, tomar decisiones, resolver bugs, documentar, ayudar a compañeros, planificar entregas... y todo esto mientras intentas mantener cierta calma mental y no olvidar nada importante.&lt;/p&gt;
&lt;p&gt;Durante mucho tiempo, yo también iba semana a semana apagando fuegos. Tenía tareas sueltas por todas partes, proyectos a medias, ideas que nunca anotaba, y una sensación constante de que algo se me escapaba.&lt;/p&gt;
&lt;p&gt;Todo cambió cuando empecé a aplicar GTD (&quot;Getting Things Done&quot;) con una revisión semanal constante. Hoy te cuento por qué eso marcó la diferencia, y cómo he creado un kit para que tú también puedas aplicarlo en tu semana como desarrollador.&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;La revisión semanal: el ancla de mi organización&lt;/h2&gt;
&lt;p&gt;GTD es una metodología de productividad que se basa en tener un sistema fiable para capturar, organizar y revisar todo lo que tienes en la cabeza. Pero si hay un paso clave, ese es la &lt;strong&gt;revisión semanal&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Es el momento en que paras, tomas perspectiva y ordenas tu mundo. En 30 minutos puedes recuperar el control, decidir en qué vas a enfocar tu atención y empezar la semana con claridad mental.&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;Cómo hago mi revisión semanal&lt;/h2&gt;
&lt;p&gt;Cada viernes, abro mi sistema y hago lo siguiente:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Vaciar mi cabeza&lt;/strong&gt;: anoto ideas, tareas pendientes, recordatorios...&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Revisar mis proyectos&lt;/strong&gt;: qué está en curso, qué necesita una acción.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Mirar mi calendario&lt;/strong&gt;: compromisos, huecos reales, eventos clave.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Revisar tareas delegadas o esperando&lt;/strong&gt;: seguimiento y control.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Organizar lo importante&lt;/strong&gt;: etiquetar, reagrupar, eliminar lo innecesario.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Revisar lo que completé esa semana&lt;/strong&gt;: sirve para motivarme y cerrar ciclo.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Uso herramientas como &lt;strong&gt;Todoist&lt;/strong&gt; para las tareas, &lt;strong&gt;Notion&lt;/strong&gt; para reflejar la revisión y un pequeño script en Node.js que me resume automáticamente mis tareas completadas por proyecto.&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;He creado un kit descargable con todo esto&lt;/h2&gt;
&lt;p&gt;Me lo han preguntado varias veces, así que decidí empaquetar mi sistema en un kit descargable que cualquiera pueda usar desde ya.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Revisión Pro: GTD para desarrolladores&lt;/strong&gt; incluye:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Una &lt;strong&gt;guía PDF&lt;/strong&gt; con el paso a paso que sigo cada semana&lt;/li&gt;
&lt;li&gt;Una &lt;strong&gt;plantilla en Notion&lt;/strong&gt; lista para usar y registrar tus revisiones&lt;/li&gt;
&lt;li&gt;Un &lt;strong&gt;script en Node.js&lt;/strong&gt; para generar tu resumen desde Todoist&lt;/li&gt;
&lt;li&gt;Mis &lt;strong&gt;filtros y etiquetas GTD personales&lt;/strong&gt; que puedes importar&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Todo en un solo ZIP, con instrucciones y ejemplos incluidos. Ideal si eres desarrollador y quieres tener el control de tu semana sin complicarte la vida.&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;Puedes conseguirlo aquí&lt;/h2&gt;
&lt;p&gt;Está disponible en Gumroad por solo &lt;strong&gt;€19&lt;/strong&gt;:
👉 &lt;a href=&quot;https://fransiner.gumroad.com/l/revision-pro-gtd-kit&quot;&gt;Accede al kit aquí&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Con una sola revisión semanal ya puedes notar la diferencia. Si te ayuda, me encantará recibir tu feedback. Y si hay interés, prepararé más kits y herramientas relacionadas con organización, automatización y productividad para desarrolladores.&lt;/p&gt;
&lt;p&gt;Gracias por leer, y feliz revisión 🚀&lt;/p&gt;
</content:encoded></item><item><title>De código a cultivo: cómo descubrí mi pasión por las plantas</title><link>https://franmoreno.com/blog/de-codigo-a-cultivo/</link><guid isPermaLink="true">https://franmoreno.com/blog/de-codigo-a-cultivo/</guid><pubDate>Tue, 13 May 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Durante años, mi día a día ha girado en torno al código, a los proyectos y a las pantallas. Soy desarrollador web y paso muchas horas frente al ordenador, saltando entre líneas de JavaScript, reuniones y revisiones. Pero hace poco, casi sin buscarlo, encontré un nuevo espacio de calma en un rincón inesperado: las plantas.&lt;/p&gt;
&lt;h2&gt;🌿 El primer brote&lt;/h2&gt;
&lt;p&gt;Todo empezó de forma sencilla. Una planta por aquí, un regalo por allá. No tenía mucha idea de cómo cuidarlas, más allá de lo que he podido ver a otros, pero me generaban cierta curiosidad. Con el tiempo, ese rincón verde se convirtió en algo más que decoración. Empecé a leer, a observar, a entender.&lt;/p&gt;
&lt;p&gt;La primera que me atrapó fue una planta de albahaca. Me encantaba verla crecer, oler sus hojas, y más aún, usarla para cocinar. Pronto llegaron otras: hierbabuena, tomillo, perejil... y la cosa empezó a parecerse más a un mini huerto que a un capricho pasajero.&lt;/p&gt;
&lt;h2&gt;💧 De rutina a ritual&lt;/h2&gt;
&lt;p&gt;Lo que al principio era &quot;no olvidar regar&quot; se transformó en un pequeño ritual diario. Revisar si necesitaban agua, quitar hojas secas, ver si alguna había brotado... Es curioso cómo algo tan simple puede convertirse en una forma de desconexión tan efectiva.&lt;/p&gt;
&lt;p&gt;Las plantas me obligan a parar. A mirar con atención. A respetar su ritmo, que no es el mío, ni el del mundo digital. Y eso, en medio del caos del día a día, es un pequeño lujo.&lt;/p&gt;
&lt;h2&gt;🌱 Mi pequeño huerto de ventana&lt;/h2&gt;
&lt;p&gt;Ahora mismo tengo varias aromáticas en una jardinera: albahaca, perejil y tomillo. También tengo una maceta individual con hierbabuena que me viene fenomenal para hacer infusiones de té verde con hierbabuena.&lt;/p&gt;
&lt;p&gt;Además, he empezado a usar Todoist para hacer seguimiento de sus cuidados: riego, podas, trasplantes... creando un proyecto nuevo para la gestión de las plantas, con sus tareas y notas. Si te interesa cómo organizo mis tareas y proyectos, puedes leer &lt;a href=&quot;/blog/gestionar-vida-notion-metodologia-gtd/&quot;&gt;cómo aplico GTD con Notion y Todoist&lt;/a&gt; o mi &lt;a href=&quot;/blog/flujo-gtd-semanal-desarrollador/&quot;&gt;flujo semanal GTD como desarrollador&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;🧠 Lo que me han enseñado las plantas&lt;/h2&gt;
&lt;p&gt;Cuidar plantas me ha enseñado más de lo que imaginaba. Me ha recordado que no todo es inmediato. Que a veces hay que esperar, observar, dejar espacio. Que no todo se puede forzar. Y que hay una satisfacción muy particular en ver cómo algo crece porque tú lo cuidas.&lt;/p&gt;
&lt;p&gt;Es curioso, pero he encontrado muchos paralelismos con el desarrollo de software: cuidar los detalles, tener paciencia, resolver problemas paso a paso… y sobre todo, disfrutar del proceso, no solo del resultado. Si te interesa cómo aplico esta filosofía en mis proyectos, puedes leer &lt;a href=&quot;/blog/objetivos-personales-y-profesionales-2023/&quot;&gt;mis objetivos personales y profesionales para 2023&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;🌻 ¿Y ahora qué?&lt;/h2&gt;
&lt;p&gt;Me gustaría seguir ampliando mi pequeña jungla doméstica. Estoy considerando hacer esquejes y aprender a propagar las que ya tengo.&lt;/p&gt;
&lt;p&gt;Si estás leyendo esto y nunca has tenido una planta, te animo a probar con una fácil. No necesitas mucho espacio ni experiencia, solo ganas de cuidar y un poco de constancia. A veces, una simple maceta puede transformar más de lo que imaginas.&lt;/p&gt;
</content:encoded></item><item><title>Mi Experiencia Real: Cuándo elijo Next.js y cuándo Astro para mis proyectos personales</title><link>https://franmoreno.com/blog/experiencia-nextjs-vs-astro-proyectos-personales/</link><guid isPermaLink="true">https://franmoreno.com/blog/experiencia-nextjs-vs-astro-proyectos-personales/</guid><pubDate>Sat, 26 Apr 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Si estás metido en el mundo del desarrollo web moderno, seguro que más de una vez te has enfrentado a esta pregunta al empezar un proyecto personal: ¿Elijo &lt;a href=&quot;https://nextjs.org/&quot;&gt;Next.js&lt;/a&gt; o me lanzo con &lt;a href=&quot;https://astro.build/&quot;&gt;Astro&lt;/a&gt;? Ambos son frameworks fantásticos, potentes y con comunidades activas, pero... ¿cuál es el adecuado para ti y para ese proyecto concreto?&lt;/p&gt;
&lt;p&gt;En 2025, la elección sigue siendo muy relevante. Después de haber trabajado con ambos en varios de mis side-projects, he desarrollado mi propio &quot;marco mental&quot; para decidir. En este artículo no voy a decirte cuál es objetivamente mejor (spoiler: ninguno lo es), sino que voy a compartir mi proceso real y mis criterios personales para elegir entre Next.js y Astro, basado en mi propia experiencia.&lt;/p&gt;
&lt;p&gt;Para poner un poco de contexto y cómo los percibo yo:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Astro:&lt;/strong&gt; Lo asocio inmediatamente con su concepto de &quot;&lt;a href=&quot;https://docs.astro.build/es/concepts/islands/&quot;&gt;islas de interactividad&lt;/a&gt;&quot;, su enfoque radical en enviar el mínimo JavaScript posible por defecto (¡&lt;a href=&quot;https://docs.astro.build/es/concepts/mpa-vs-spa/#cero-js-por-defecto&quot;&gt;cero JS por defecto&lt;/a&gt;!) y su excelente manejo del contenido estático (&lt;a href=&quot;https://www.markdownguide.org/basic-syntax/&quot;&gt;Markdown&lt;/a&gt;, &lt;a href=&quot;https://mdxjs.com/&quot;&gt;MDX&lt;/a&gt;). Ideal para la velocidad.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Next.js:&lt;/strong&gt; Lo veo como el gigante versátil del ecosistema &lt;a href=&quot;https://react.dev/&quot;&gt;React&lt;/a&gt;, con capacidades full-stack muy potentes (gracias al &lt;a href=&quot;https://nextjs.org/docs/app&quot;&gt;App Router&lt;/a&gt;, &lt;a href=&quot;https://nextjs.org/docs/app/building-your-application/rendering/server-components&quot;&gt;Server Components&lt;/a&gt;, &lt;a href=&quot;https://nextjs.org/docs/app/building-your-application/data-fetching/server-actions-and-mutations&quot;&gt;Server Actions&lt;/a&gt;...), una flexibilidad enorme en el renderizado y un ecosistema maduro para construir aplicaciones complejas.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;¡Vamos al lío!&lt;/p&gt;
&lt;h2&gt;Mis Criterios de Decisión Clave&lt;/h2&gt;
&lt;p&gt;Cuando evalúo si usar Next.js o Astro para un nuevo proyecto personal, me hago principalmente estas preguntas:&lt;/p&gt;
&lt;h3&gt;1. ¿Cuánta Interactividad Necesita el Proyecto y Dónde? (El Factor JavaScript)&lt;/h3&gt;
&lt;p&gt;Esta suele ser mi primera y más importante pregunta. Define en gran medida la arquitectura y el rendimiento final.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Escenario A: Interactividad Baja o Muy Localizada&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Descripción:&lt;/strong&gt; El proyecto es principalmente contenido estático (un blog, una landing page, una web de documentación, un portfolio) con puntos específicos y aislados de interacción: un carrusel de imágenes, un botón de suscripción a newsletter, quizás un buscador simple en el cliente, comentarios bajo los posts, un botón para cambiar el tema (modo oscuro/claro)...&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Mi Elección Habitual:&lt;/strong&gt; Astro&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Mis Razones (Experiencia):&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Rendimiento por Defecto Imbatible:&lt;/strong&gt; Astro envía cero JavaScript al cliente por defecto. Esto se traduce en páginas que cargan increíblemente rápido, lo cual es crucial para webs centradas en contenido donde la velocidad inicial y el SEO son prioritarios. Es una ventaja competitiva enorme.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Islas de Interactividad:&lt;/strong&gt; Cuando necesito algo de JavaScript (un componente para el modo oscuro, un formulario de contacto que valide en cliente), puedo &quot;hidratar&quot; solo ese componente específico usando una &lt;a href=&quot;https://docs.astro.build/es/reference/directives-reference/#directivas-de-cliente&quot;&gt;directiva &lt;code&gt;client:*&lt;/code&gt;&lt;/a&gt;. El resto de la página permanece como HTML estático, rápido y ligero. Lo mejor es que puedo usar componentes de &lt;a href=&quot;https://react.dev/&quot;&gt;React&lt;/a&gt;, &lt;a href=&quot;https://vuejs.org/&quot;&gt;Vue&lt;/a&gt;, &lt;a href=&quot;https://svelte.dev/&quot;&gt;Svelte&lt;/a&gt;, etc., solo donde los necesito, ¡una flexibilidad genial sin penalizar el rendimiento global!&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Developer Experience (DX) para Contenido:&lt;/strong&gt; La sintaxis de los archivos &lt;code&gt;.astro&lt;/code&gt; me resulta muy natural y productiva. Mezcla HTML con expresiones JavaScript de forma sencilla y es ideal para maquetar páginas ricas en contenido sin la complejidad de un framework &lt;a href=&quot;https://developer.mozilla.org/es/docs/Glossary/SPA&quot;&gt;SPA&lt;/a&gt; completo.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Ejemplo Personal:&lt;/strong&gt;
Mi propia web personal, &lt;a href=&quot;https://franmoreno.com&quot;&gt;&lt;code&gt;franmoreno.com&lt;/code&gt;&lt;/a&gt;, es un claro ejemplo. Está construida con Astro. El núcleo de la web es el contenido (artículos del blog escritos en Markdown, páginas estáticas...). La interactividad es mínima y localizada (algún botón o componente específico). Astro me permite tener un rendimiento excelente y gestionar el contenido de forma muy cómoda, sin la sobrecarga de JavaScript innecesario.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Escenario B: Interactividad Alta, Compleja o Global&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Descripción:&lt;/strong&gt; Necesito una experiencia de usuario muy dinámica, más cercana a una aplicación web (&lt;a href=&quot;https://developer.mozilla.org/es/docs/Glossary/SPA&quot;&gt;SPA&lt;/a&gt;) o incluso una aplicación de escritorio. Hablamos de dashboards con múltiples filtros interactivos, estado que se comparte y sincroniza entre muchas partes de la UI, interfaces complejas que reaccionan en tiempo real a las acciones del usuario, gestión de usuarios (login, perfiles), lógica de negocio significativa en el frontend...&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Mi Elección Habitual:&lt;/strong&gt; Next.js&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Mis Razones (Experiencia):&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Ecosistema React Maduro:&lt;/strong&gt; Para aplicaciones complejas, el ecosistema maduro de React es una ventaja inmensa. Librerías de componentes UI (como &lt;a href=&quot;https://ui.shadcn.com/&quot;&gt;Shadcn/UI&lt;/a&gt;, &lt;a href=&quot;https://mui.com/&quot;&gt;Material UI&lt;/a&gt;, &lt;a href=&quot;https://chakra-ui.com/&quot;&gt;Chakra UI&lt;/a&gt;...), herramientas robustas de gestión de estado (&lt;a href=&quot;https://zustand-demo.pmnd.rs/&quot;&gt;Zustand&lt;/a&gt;, &lt;a href=&quot;https://react.dev/learn/passing-data-deeply-with-context&quot;&gt;Context API&lt;/a&gt;, &lt;a href=&quot;https://redux.js.org/&quot;&gt;Redux&lt;/a&gt;, &lt;a href=&quot;https://jotai.org/&quot;&gt;Jotai&lt;/a&gt;)...), librerías para visualización de datos (&lt;a href=&quot;https://recharts.org/&quot;&gt;Recharts&lt;/a&gt;, &lt;a href=&quot;https://nivo.rocks/&quot;&gt;Nivo&lt;/a&gt;)...), etc., están fácilmente disponibles, bien documentadas y se integran sin fricciones.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Gestión del Estado Sofisticada:&lt;/strong&gt; En aplicaciones con mucha interacción, gestionar el estado de forma coherente y escalable es vital. Next.js, al estar basado en React, me permite usar patrones y herramientas probadas (Context, hooks, librerías de estado) para manejar tanto el estado local de los componentes como el estado global de la aplicación de forma eficiente.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Capacidades Full-Stack Integradas:&lt;/strong&gt; Con el App Router, los Server Components (RSC) y las Server Actions, puedo definir lógica de backend (acceso a bases de datos, llamadas a APIs externas, autenticación, procesamiento de formularios) directamente dentro de mi proyecto Next.js. Esto simplifica enormemente la arquitectura para muchos tipos de aplicaciones, evitando tener que gestionar un backend separado si no es estrictamente necesario.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Flexibilidad en el Renderizado:&lt;/strong&gt; Puedo elegir estratégicamente cómo renderizar cada parte de la aplicación (&lt;a href=&quot;https://developer.mozilla.org/es/docs/Glossary/Server-side_rendering&quot;&gt;Server-Side Rendering - SSR&lt;/a&gt;, &lt;a href=&quot;https://developer.mozilla.org/es/docs/Glossary/Static_site_generation&quot;&gt;Static Site Generation - SSG&lt;/a&gt;, &lt;a href=&quot;https://nextjs.org/docs/pages/building-your-application/data-fetching/incremental-static-regeneration&quot;&gt;Incremental Static Regeneration - ISR&lt;/a&gt;, &lt;a href=&quot;https://developer.mozilla.org/es/docs/Glossary/Client-side_rendering&quot;&gt;Client-Side Rendering - CSR&lt;/a&gt;) según las necesidades específicas, optimizando tanto el rendimiento como la frescura de los datos.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Ejemplo Personal:&lt;/strong&gt;
Actualmente estoy desarrollando un proyecto (aún no público) que es esencialmente una aplicación web compleja. Incluye un panel de administración, un área privada para usuarios con registro y gestión de suscripciones, dashboards con gráficas interactivas que muestran datos en tiempo real, y generación de informes. Para este tipo de proyecto, con tanta lógica de negocio, gestión de estado compleja y necesidad de interactividad rica, Next.js fue la elección clara desde el principio. Me permite aprovechar todo el ecosistema React y las capacidades full-stack integradas para construir la aplicación de manera más eficiente y estructurada.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;2. ¿Cuál es la Naturaleza del Contenido y la Necesidad de Dinamismo?&lt;/h3&gt;
&lt;p&gt;El tipo de contenido y cómo/cuándo se actualiza es otro factor fundamental.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Escenario A: Contenido Mayoritariamente Estático o Generado en Build Time&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Descripción:&lt;/strong&gt; La gran mayoría del contenido se puede generar cuando construyo el sitio (en el build time) y no cambia con cada petición del usuario. Blogs, portfolios, webs de documentación, landings promocionales...&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Mi Elección Habitual:&lt;/strong&gt; Astro&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Mis Razones (Experiencia):&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Content Collections:&lt;/strong&gt; Para sitios ricos en contenido como blogs o documentación, las &lt;a href=&quot;https://docs.astro.build/es/guides/content-collections/&quot;&gt;Content Collections de Astro&lt;/a&gt; son una auténtica maravilla. Te permiten organizar tus archivos Markdown o MDX en carpetas, definir un esquema (schema) para el frontmatter usando &lt;a href=&quot;https://zod.dev/&quot;&gt;Zod&lt;/a&gt; (asegurando así que todos los posts tengan título, fecha, autor, etc., y con el tipo de dato correcto), y luego consultar ese contenido de forma segura y tipada en tus páginas &lt;code&gt;.astro&lt;/code&gt;. Simplifica enormemente la gestión del contenido y evita errores tontos.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Optimización para SSG (Static Site Generation):&lt;/strong&gt; Astro está diseñado principalmente para generar sitios estáticos. Construye todas las páginas HTML en el momento del despliegue (o en tu máquina antes de subirlo). Esto resulta en un rendimiento excelente, gran seguridad (menos superficie de ataque al no haber servidor ejecutando código por petición) y fácil despliegue en cualquier hosting estático (&lt;a href=&quot;https://www.netlify.com/&quot;&gt;Netlify&lt;/a&gt;, &lt;a href=&quot;https://vercel.com/&quot;&gt;Vercel&lt;/a&gt;, &lt;a href=&quot;https://pages.cloudflare.com/&quot;&gt;Cloudflare Pages&lt;/a&gt;, &lt;a href=&quot;https://pages.github.com/&quot;&gt;GitHub Pages&lt;/a&gt;...). Puedes activar el modo SSR si lo necesitas, pero su fuerte es el SSG.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Ejemplo Personal:&lt;/strong&gt;
De nuevo, mi web &lt;code&gt;franmoreno.com&lt;/code&gt; encaja perfectamente aquí. Utilizo las Content Collections para gestionar todos los artículos del blog. Defino un esquema para asegurar que cada post tenga los campos necesarios (título, descripción, fecha de publicación, imagen de portada...) y Astro me ayuda a obtener y mostrar esa información de forma segura y sencilla. La generación estática hace que el blog sea rapidísimo.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Escenario B: Contenido Dinámico, Personalizado, Rutas Protegidas o Dependiente de APIs Externas&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Descripción:&lt;/strong&gt; Necesito mostrar contenido diferente según el usuario que ha iniciado sesión, conectar a bases de datos para obtener datos actualizados en tiempo real, tener áreas privadas (rutas protegidas por login), o mostrar contenido que cambia muy frecuentemente y que proviene de fuentes externas como APIs &lt;a href=&quot;https://developer.mozilla.org/es/docs/Glossary/REST&quot;&gt;REST&lt;/a&gt; o &lt;a href=&quot;https://graphql.org/&quot;&gt;GraphQL&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Mi Elección Habitual:&lt;/strong&gt; Next.js&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Mis Razones (Experiencia):&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Fetching de Datos Flexible y Potente:&lt;/strong&gt; Next.js (especialmente con el App Router y los Server Components) ofrece múltiples y potentes formas de obtener datos: en el servidor (durante el renderizado SSR o al construir Server Components), en el cliente (con hooks como &lt;a href=&quot;https://react.dev/reference/react/useEffect&quot;&gt;&lt;code&gt;useEffect&lt;/code&gt;&lt;/a&gt; o librerías como &lt;a href=&quot;https://swr.vercel.app/&quot;&gt;SWR&lt;/a&gt;/&lt;a href=&quot;https://tanstack.com/query/latest&quot;&gt;React Query&lt;/a&gt;) o de forma incremental (ISR). Esto es ideal para consumir APIs. Puedes obtener los datos en el servidor para el renderizado inicial (mejorando el SEO y el rendimiento percibido) y luego actualizarlos o revalidarlos en el cliente si es necesario.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Server Actions / API Routes:&lt;/strong&gt; Si necesito realizar operaciones que modifican datos (mutaciones) como enviar un formulario, actualizar datos del perfil de usuario, añadir un producto al carrito, etc., las &lt;a href=&quot;https://nextjs.org/docs/app/building-your-application/data-fetching/server-actions-and-mutations&quot;&gt;Server Actions&lt;/a&gt; (en App Router) o las &lt;a href=&quot;https://nextjs.org/docs/pages/building-your-application/routing/api-routes&quot;&gt;API Routes&lt;/a&gt; (en Pages Router o App Router) de Next.js me permiten crear endpoints seguros dentro del mismo proyecto. Puedo interactuar con mi base de datos o APIs externas sin exponer lógica sensible o credenciales en el navegador del cliente.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Gestión de Autenticación Integrada:&lt;/strong&gt; Integrar sistemas de autenticación (como &lt;a href=&quot;https://next-auth.js.org/&quot;&gt;NextAuth.js&lt;/a&gt;, &lt;a href=&quot;https://clerk.com/&quot;&gt;Clerk&lt;/a&gt;, u otros proveedores) para proteger rutas y personalizar el contenido según el usuario conectado es un proceso más directo y con más recursos disponibles en Next.js, dado su enfoque de aplicación completa. Hay muchos tutoriales y ejemplos específicos.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Ejemplo Personal:&lt;/strong&gt;
He desarrollado un área de clientes para un proyecto freelance utilizando Next.js. Toda la información que se muestra (datos del usuario, historial de pedidos, facturas descargables, etc.) proviene íntegramente de una API REST externa. Next.js me facilita enormemente el trabajo: uso Server Components para hacer las llamadas a la API en el servidor al cargar las páginas (asegurando que los datos están actualizados), gestiono la autenticación del usuario con NextAuth.js para proteger el acceso, y uso Client Components con librerías como SWR para volver a validar datos o realizar actualizaciones (ej: cambiar dirección) sin recargar la página completa. Intentar replicar esto con un enfoque puramente estático como el de Astro por defecto sería mucho más complejo y requeriría soluciones más &quot;manuales&quot;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;3. ¿Cómo Afecta a Mi Flujo de Desarrollo (Developer Experience - DX)?&lt;/h3&gt;
&lt;p&gt;Aunque a veces es secundario frente a los requisitos técnicos, cómo me siento desarrollando y cuán productivo soy también influye en mi elección, especialmente en proyectos personales donde el disfrute es importante.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Curva de Aprendizaje:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Astro:&lt;/strong&gt; Para mí, la curva de aprendizaje de Astro es significativamente más suave, especialmente si vienes del desarrollo web más tradicional (HTML, CSS, JS) o si no tienes una base fuerte en React. Con conceptos básicos es suficiente para empezar a construir sitios eficientes rápidamente. La sintaxis de los archivos &lt;code&gt;.astro&lt;/code&gt; es muy intuitiva. No necesitas entender conceptos complejos de React (hooks, estado global, contexto) para ser productivo desde el minuto uno en proyectos centrados en contenido.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Next.js:&lt;/strong&gt; Si ya tienes una base sólida en React, empezar con Next.js (especialmente con el antiguo Pages Router) es bastante natural. Sin embargo, dominar las características más modernas y potentes como el &lt;a href=&quot;https://nextjs.org/docs/app&quot;&gt;App Router&lt;/a&gt;, los &lt;a href=&quot;https://nextjs.org/docs/app/building-your-application/rendering/server-components&quot;&gt;Server Components (RSC)&lt;/a&gt;, las &lt;a href=&quot;https://nextjs.org/docs/app/building-your-application/data-fetching/server-actions-and-mutations&quot;&gt;Server Actions&lt;/a&gt; y las sutilezas del renderizado mixto (&lt;a href=&quot;https://developer.mozilla.org/es/docs/Glossary/Server-side_rendering&quot;&gt;SSR&lt;/a&gt;/&lt;a href=&quot;https://developer.mozilla.org/es/docs/Glossary/Static_site_generation&quot;&gt;SSG&lt;/a&gt;/&lt;a href=&quot;https://nextjs.org/docs/pages/building-your-application/data-fetching/incremental-static-regeneration&quot;&gt;ISR&lt;/a&gt;/&lt;a href=&quot;https://developer.mozilla.org/es/docs/Glossary/Client-side_rendering&quot;&gt;Client&lt;/a&gt;) requiere un esfuerzo adicional y entender conceptos más avanzados. La curva se empina si quieres aprovechar todo su potencial full-stack, aunque la documentación oficial es muy buena.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Ecosistema y Herramientas:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Next.js:&lt;/strong&gt; Aquí es donde Next.js (y por extensión, React) realmente brilla por su madurez y tamaño. La comunidad es gigantesca, lo que significa que hay una cantidad enorme de librerías, herramientas, tutoriales, artículos y soluciones a problemas comunes disponibles. Si tienes una duda o necesitas una funcionalidad específica (un componente de UI particular, una librería de animación, una solución de autenticación), es muy probable que alguien ya la haya resuelto o creado una herramienta para ello. Esto acelera mucho el desarrollo de aplicaciones complejas.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Astro:&lt;/strong&gt; Su ecosistema está creciendo muy rápidamente y es muy activo, con integraciones oficiales muy bien cuidadas (&lt;a href=&quot;https://tailwindcss.com/&quot;&gt;Tailwind&lt;/a&gt;, &lt;a href=&quot;https://mdxjs.com/&quot;&gt;MDX&lt;/a&gt;, &lt;a href=&quot;https://partytown.builder.io/&quot;&gt;Partytown&lt;/a&gt;, frameworks UI...). Sin embargo, es innegable que es más joven y, por tanto, más pequeño que el de React/Next.js. A veces puedes encontrar menos ejemplos o librerías específicas para casos de uso muy concretos, aunque la documentación oficial es excelente y la comunidad en &lt;a href=&quot;https://astro.build/chat&quot;&gt;Discord&lt;/a&gt; es muy colaborativa y dispuesta a ayudar.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;4. Despliegue y Hosting&lt;/h3&gt;
&lt;p&gt;Aunque ambos frameworks son flexibles, hay matices:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Astro (Modo SSG por defecto):&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Ventaja:&lt;/strong&gt; Genera archivos estáticos (HTML, CSS, JS). Puedes desplegarlo en cualquier hosting estático, muchos de ellos gratuitos o muy económicos (&lt;a href=&quot;https://www.netlify.com/&quot;&gt;Netlify&lt;/a&gt;, &lt;a href=&quot;https://vercel.com/&quot;&gt;Vercel&lt;/a&gt;, &lt;a href=&quot;https://pages.cloudflare.com/&quot;&gt;Cloudflare Pages&lt;/a&gt; – &lt;em&gt;sobre el que puedes leer mi experiencia moviendo proyectos &lt;a href=&quot;/blog/moviendo-mis-side-projects-a-cloudflare/&quot;&gt;aquí&lt;/a&gt;&lt;/em&gt; –, &lt;a href=&quot;https://pages.github.com/&quot;&gt;GitHub Pages&lt;/a&gt;, &lt;a href=&quot;https://aws.amazon.com/s3/&quot;&gt;AWS S3&lt;/a&gt;...). Es simple y robusto.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Consideración:&lt;/strong&gt; Si activas el modo SSR (Server-Side Rendering), necesitarás un entorno que pueda ejecutar &lt;a href=&quot;https://nodejs.org/&quot;&gt;Node.js&lt;/a&gt; (como Vercel, Netlify Functions, un servidor propio, etc.), similar a Next.js.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Next.js:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Ventaja:&lt;/strong&gt; Plataformas como &lt;a href=&quot;https://vercel.com/&quot;&gt;Vercel&lt;/a&gt; (los creadores de Next.js) ofrecen una integración perfecta y optimizada, aprovechando todas sus características (SSR, ISR, Server Actions, &lt;a href=&quot;https://vercel.com/docs/functions/edge-functions&quot;&gt;Edge Functions&lt;/a&gt;...).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Consideración:&lt;/strong&gt; Si usas funcionalidades avanzadas (SSR, ISR, Server Actions), generalmente necesitarás un hosting que soporte &lt;a href=&quot;https://nodejs.org/&quot;&gt;Node.js&lt;/a&gt; o plataformas específicas (Vercel, Netlify, AWS Amplify...). Desplegar en hosting puramente estático es posible si solo usas SSG, pero limita el potencial del framework.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;5. Comunidad y Soporte&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Next.js:&lt;/strong&gt; Tiene una de las comunidades más grandes y activas en el desarrollo web. Encontrarás respuestas en &lt;a href=&quot;https://stackoverflow.com/&quot;&gt;Stack Overflow&lt;/a&gt;, &lt;a href=&quot;https://github.com/vercel/next.js/discussions&quot;&gt;GitHub Discussions&lt;/a&gt;, blogs, YouTube, etc., para casi cualquier problema. El soporte de Vercel es también un punto fuerte.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Astro:&lt;/strong&gt; Comunidad más pequeña pero muy entusiasta, amigable y en rápido crecimiento. Su servidor de &lt;a href=&quot;https://astro.build/chat&quot;&gt;Discord&lt;/a&gt; es especialmente activo y útil para obtener ayuda directa. La documentación oficial es de alta calidad.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Mis Proyectos Como Ejemplo&lt;/h2&gt;
&lt;p&gt;Para ilustrar mi proceso de decisión, aquí algunos ejemplos reales:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Proyecto A: Mi Web Personal (&lt;code&gt;franmoreno.com&lt;/code&gt;) - Elegí Astro&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Justificación:&lt;/strong&gt; Sitio centrado 100% en contenido (blog en Markdown, páginas estáticas). Requisitos: máximo rendimiento posible (carga rápida, buen score en &lt;a href=&quot;https://developer.chrome.com/docs/lighthouse/&quot;&gt;Lighthouse&lt;/a&gt;) y una gestión sencilla del contenido. La interactividad es mínima y aislada.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Resultado:&lt;/strong&gt; Astro fue la elección perfecta. El sitio es increíblemente rápido, las Content Collections son una gozada para gestionar el blog, y la DX para maquetar las páginas fue muy agradable y directa. No necesitaba la complejidad ni el JavaScript de React para este caso.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Proyecto B: &lt;code&gt;TorneosPokerLive.com&lt;/code&gt; - Elegí Next.js (¡Tras una Migración desde Astro!)&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Justificación Inicial (Astro):&lt;/strong&gt; Este proyecto empezó como una web para mostrar información estática/semi-estática de torneos de póker en vivo (contenido). Astro parecía una buena opción por su rendimiento y manejo de contenido.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;La Necesidad de Migrar:&lt;/strong&gt; Sin embargo, el plan a largo plazo siempre fue añadir funcionalidades complejas para usuarios: registro/login, seguimiento de casinos favoritos, comentarios, notificaciones, quizás incluso compra de entradas en un futuro. Me di cuenta de que para escalar hacia esas funcionalidades, necesitaría un framework con capacidades full-stack más robustas, mejor gestión de estado y un ecosistema más preparado para aplicaciones web interactivas. Además, quería practicar y profundizar en Next.js con el App Router.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Resultado (Next.js):&lt;/strong&gt; Migré el proyecto a Next.js. Aunque supuso rehacer parte del trabajo inicial, ahora tengo una base mucho más sólida y escalable para implementar las futuras funcionalidades de usuario. Puedo usar Server Components para cargar datos dinámicos, Server Actions para las interacciones con la base de datos, integrar fácilmente autenticación y aprovechar todo el ecosistema React para construir la interfaz de usuario compleja que necesitaré. Si el proyecto se hubiera quedado solo en mostrar contenido, me habría quedado felizmente en Astro, pero la visión a futuro justificó el cambio.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Proyecto C: Aplicación SaaS Interna (No pública) - Elegí Next.js&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Justificación:&lt;/strong&gt; Una aplicación web con dashboard, gestión de usuarios, conexión a base de datos, formularios complejos, generación de reportes PDF, integración con APIs externas. Claramente un caso de uso de aplicación interactiva (&lt;a href=&quot;https://es.wikipedia.org/wiki/Software_como_servicio&quot;&gt;SaaS&lt;/a&gt;) y con lógica de negocio.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Resultado:&lt;/strong&gt; Next.js fue la elección obvia y acertada. El App Router, Server Components y Server Actions permiten una arquitectura coherente y eficiente. El ecosistema React proporciona todas las herramientas necesarias para la UI y la gestión de estado.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Conclusión: El Contexto Manda Sobre la Herramienta&lt;/h2&gt;
&lt;p&gt;Al final del día, mi filosofía es clara y creo que es la más sensata: el contexto y los requisitos específicos del proyecto mandan sobre la elección de la herramienta. No hay un &quot;mejor&quot; framework universal.&lt;/p&gt;
&lt;p&gt;Para resumir mi enfoque personal en 2025:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Elijo Astro cuando:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;La prioridad número uno es el rendimiento y la velocidad de carga (sitios de contenido, landings).&lt;/li&gt;
&lt;li&gt;El contenido es el rey (blogs, documentación, portfolios).&lt;/li&gt;
&lt;li&gt;La interactividad es mínima o muy localizada (islas de JS).&lt;/li&gt;
&lt;li&gt;Quiero una DX sencilla y directa para maquetar y gestionar contenido.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Elijo Next.js cuando:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Necesito construir una aplicación web compleja e interactiva (dashboards, áreas de usuario, SaaS).&lt;/li&gt;
&lt;li&gt;El dinamismo, la personalización y los datos en tiempo real son fundamentales.&lt;/li&gt;
&lt;li&gt;Quiero aprovechar el enorme ecosistema de React (librerías de UI, estado, etc.).&lt;/li&gt;
&lt;li&gt;Necesito capacidades full-stack integradas (Server Components, Server Actions, API Routes).&lt;/li&gt;
&lt;li&gt;Preveo una escalabilidad futura hacia funcionalidades de aplicación complejas, incluso si empiezo con algo más simple. (¡Este punto es clave y a menudo justifica elegir Next.js desde el principio!)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Esto es lo que me funciona a mí, basado en mis experiencias y el tipo de proyectos personales que suelo abordar. ¡Puede que tu caso, tus prioridades o tu experiencia previa te lleven a conclusiones diferentes!&lt;/p&gt;
&lt;p&gt;La mejor recomendación que puedo darte es: experimenta. Monta un proyecto pequeño con ambos frameworks si tienes dudas. Siente la Developer Experience, prueba las funcionalidades clave que necesitas para tu caso de uso y decide por ti mismo cuál se adapta mejor.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Si quieres explorar otras herramientas modernas para desarrollo full-stack, también puedes echar un vistazo a &lt;a href=&quot;/blog/3-herramientas-desarrollo-fullstack-2025/&quot;&gt;este post&lt;/a&gt;&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Y ahora te pregunto a ti: ¿Qué te hace decidir entre Next.js y Astro? ¿Usas criterios similares? ¿Hay algún factor clave que se me haya escapado? ¡Me encantaría leer tu experiencia y tu opinión en los comentarios!&lt;/p&gt;
</content:encoded></item><item><title>Mi Flujo GTD Semanal como Desarrollador: Herramientas y Rutinas para Mantener a Raya Proyectos Personales y Profesionales</title><link>https://franmoreno.com/blog/flujo-gtd-semanal-desarrollador/</link><guid isPermaLink="true">https://franmoreno.com/blog/flujo-gtd-semanal-desarrollador/</guid><pubDate>Sat, 19 Apr 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;¿Te suena esta imagen? Lunes por la mañana. Tienes abierto Cursor/VSCode/WebStorm/etc con varios proyectos, veinte pestañas en el navegador (documentación, Stack Overflow, Jira, GitHub, ChatGPT, el build fallido de anoche...), Slack/Teams/Gather explotando con notificaciones, el email pidiendo atención y, en algún lugar de tu mente, la vaga idea de ese &lt;em&gt;side-project&lt;/em&gt; que querías empezar o ese curso de Kubernetes que te prometiste hacer. Estás en modo bombero, apagando fuegos, respondiendo a lo urgente, pero con la constante sensación de que las cosas importantes – las que realmente te hacen avanzar profesional y personalmente – se quedan atrás. Te sientes agobiado, quizás un poco quemado, y la idea de &quot;perder el control&quot; no es una metáfora, es tu realidad diaria.&lt;/p&gt;
&lt;p&gt;El problema es real: como desarrolladores, manejamos un montón de cosas complejas. Proyectos del trabajo con fechas de entrega ajustadas, bugs inesperados que echan por tierra los planes, la necesidad constante de aprender nuevas tecnologías, mantener nuestros propios proyectos o contribuciones open-source, y además, intentar tener una vida fuera del código. ¿Cómo gestionar todo esto sin que la cabeza explote? ¿Cómo asegurarnos de que dedicamos tiempo a construir el futuro y no solo a parchear el presente?&lt;/p&gt;
&lt;p&gt;Aquí es donde entra en juego GTD (Getting Things Done). Pero no te asustes, no vengo a venderte un sistema rígido y complicado. Para mí, GTD es una caja de herramientas mentales y una filosofía con ideas clave &lt;em&gt;(si quieres una introducción, puedes leer &lt;a href=&quot;/blog/gestionar-vida-notion-metodologia-gtd/&quot;&gt;este otro post&lt;/a&gt;)&lt;/em&gt;. Y una de las más potentes, la que me devuelve la cordura semana tras semana, es la &lt;strong&gt;Revisión Semanal&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;En este artículo, quiero compartir contigo mi sistema personal y práctico de revisión semanal GTD, adaptado específicamente a los líos que tenemos como desarrolladores. Te contaré mi rutina, las herramientas concretas que uso (mi &quot;stack&quot; de productividad) y cómo las uno para mantenerme centrado, reducir el estrés y asegurar que tanto mi trabajo como mis proyectos personales avanzan de forma constante.&lt;/p&gt;
&lt;h2&gt;¿Por Qué una Revisión Semanal es CRUCIAL para un Desarrollador?&lt;/h2&gt;
&lt;p&gt;Antes de entrar en el &quot;cómo&quot;, déjame convencerte del &quot;por qué&quot;. Puede parecer una tarea más en una agenda ya llena, pero para mí, la revisión semanal es la inversión que hace que el resto de la semana vaya mejor. Estos son los beneficios principales que noto:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Ganar Perspectiva:&lt;/strong&gt; Es mi momento para salir del código, de la tarea inmediata, del bug urgente. Me permite levantar la cabeza y ver el &quot;cuadro completo&quot;: todos mis proyectos (trabajo, personales, de aprendizaje), mis responsabilidades y mis objetivos a medio plazo. Paso del modo &quot;apagar fuegos&quot; al modo &quot;arquitecto&quot;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Controlar el Flujo:&lt;/strong&gt; Los desarrolladores somos como imanes para la información: emails, avisos de Slack/Teams, menciones en GitHub/GitLab, tickets en Jira/Azure DevOps, ideas para refactorizar, enlaces interesantes, notas rápidas... La revisión semanal es mi forma de &quot;vaciar&quot; todas esas bandejas de entrada mentales y digitales, asegurando que no se nos escape nada importante entre tanto lío.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Enfocarse en lo Importante:&lt;/strong&gt; Es fácil que lo urgente se coma todo el tiempo. Reuniones, interrupciones, bugs críticos... pueden ocupar todo nuestro día. La revisión me ayuda a encontrar y proteger tiempo y energía para las tareas que de verdad marcan la diferencia: bloques de desarrollo concentrado (&lt;em&gt;deep work&lt;/em&gt;), aprendizaje, planificación de un proyecto, etc.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Reducir Estrés y Ansiedad:&lt;/strong&gt; Esa sensación molesta de &quot;seguro que me estoy olvidando de algo&quot; desaparece (o casi). Saber que he repasado todo, que todo está apuntado y que tengo un plan (flexible, eso sí) para la semana siguiente, me da una tranquilidad que no tiene precio.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Adaptabilidad:&lt;/strong&gt; El desarrollo de software es cambio constante. Prioridades que cambian, requisitos que evolucionan, problemas inesperados... La revisión semanal me da el momento para pensar en estos cambios, ajustar mis planes y reordenar mis tareas con cabeza, en lugar de ir dando bandazos.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;Mi Rutina: Preparando el Terreno para la Claridad&lt;/h2&gt;
&lt;p&gt;Ser constante es fundamental. Para que la revisión funcione, tiene que ser un hábito sagrado. Así es como lo hago yo:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;El Momento Sagrado:&lt;/strong&gt; Mi momento es el &lt;strong&gt;viernes por la tarde&lt;/strong&gt;, normalmente al finalizar el día de trabajo. ¿Por qué? Me permite cerrar la semana con la mente clara, sabiendo lo que he hecho y lo que viene. Empiezo el fin de semana desconectado de verdad y el lunes sé por dónde empezar. Probé el domingo por la noche, pero me daba estrés pre-lunes; el viernes me va mejor para &quot;cerrar la persiana&quot;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;El Entorno:&lt;/strong&gt; Intento concentrarme al máximo. Eso significa:
&lt;ul&gt;
&lt;li&gt;Notificaciones de Slack, email y móvil &lt;strong&gt;apagadas&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;A veces, cascos con música tranquila (¡sin letra!).&lt;/li&gt;
&lt;li&gt;Un buen café o té para el ritual.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Duración Estimada:&lt;/strong&gt; Normalmente me lleva entre &lt;strong&gt;30 y 60 minutos&lt;/strong&gt;. Al principio igual tardas más, pero le pillas el truco. Si una semana voy a tope, igual se alarga un poco, pero intento no saltármela nunca, aunque sea una versión rápida.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Herramientas a Mano:&lt;/strong&gt; Antes de empezar, me aseguro de tener todo preparado:
&lt;ul&gt;
&lt;li&gt;El ordenador con acceso a mis herramientas.&lt;/li&gt;
&lt;li&gt;Mi libreta física por si apunté algo ahí.&lt;/li&gt;
&lt;li&gt;Mi app de tareas abierta.&lt;/li&gt;
&lt;li&gt;Mi calendario a la vista.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;El Proceso Paso a Paso de Mi Revisión Semanal&lt;/h2&gt;
&lt;p&gt;Vale, vamos al lío. Mi proceso sigue las ideas de GTD, pero a mi manera como desarrollador. Recuerda: el objetivo es tener la mente despejada y confiar en tu sistema.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;(Recordatorio GTD: Recopilar -&amp;gt; Procesar -&amp;gt; Organizar -&amp;gt; Revisar -&amp;gt; Hacer)&lt;/strong&gt; La Revisión Semanal se centra sobre todo en &lt;strong&gt;Recopilar&lt;/strong&gt; lo pendiente, &lt;strong&gt;Procesar&lt;/strong&gt; lo nuevo, &lt;strong&gt;Organizar&lt;/strong&gt; y &lt;strong&gt;Revisar&lt;/strong&gt; todo el sistema.&lt;/p&gt;
&lt;h3&gt;1. Recopilar y Vaciar TODO:&lt;/h3&gt;
&lt;p&gt;El primer paso es sacar todo de la cabeza y de todas las &quot;bandejas de entrada&quot;. Reviso:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Físicas:&lt;/strong&gt; Papeles sueltos, notas en mi libreta.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Digitales:&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;Email (Personal y Trabajo): Dejar la bandeja de entrada a cero.&lt;/li&gt;
&lt;li&gt;Notas Rápidas (Ej: Apple Notes, Google Keep, un &lt;code&gt;notes.txt&lt;/code&gt;): Cualquier cosa apuntada rápido.&lt;/li&gt;
&lt;li&gt;Carpeta de Descargas: ¿Hay algo ahí que guardar o borrar?&lt;/li&gt;
&lt;li&gt;Mensajes Directos (Slack/Teams): ¿Alguna petición o info pendiente?&lt;/li&gt;
&lt;li&gt;Mi App de Tareas Principal (Ej: Notion, Todoist...): La bandeja de entrada donde apunto cosas durante la semana.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Mental:&lt;/strong&gt; ¿Qué me preocupa? ¿Qué ideas tengo? ¿Qué tengo que recordar? ¡Todo fuera y apuntado en la bandeja de entrada digital!&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;2. Procesar lo Recopilado:&lt;/h3&gt;
&lt;p&gt;Ahora, miro cada cosa que he recopilado, una por una, con la lógica GTD:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;¿Hay que hacer algo?&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;No:&lt;/strong&gt; Archivar como referencia (luego vemos dónde) o borrar si no sirve.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Sí:&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;¿Se hace en menos de 2 minutos?&lt;/strong&gt; ¡Hazlo ya! (Responder un email corto, crear una tarea fácil).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;¿No es para mí?&lt;/strong&gt; Pásalo a quien toque (y si quieres, apúntalo en tu lista &quot;A la Espera&quot;).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;¿Es para un día/hora concretos?&lt;/strong&gt; Al Calendario (reuniones, citas, recordatorios de entregas).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;¿Es parte de algo más grande o necesita varios pasos?&lt;/strong&gt; Define la &lt;strong&gt;&quot;Próxima Acción&quot;&lt;/strong&gt;: el siguiente paso concreto y real que hay que dar. Añádela a tu lista de &quot;Próximas Acciones&quot;. Si es de un proyecto, ponle una etiqueta o vincúlala a él.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;¿Es algo que quiero hacer, pero no ahora?&lt;/strong&gt; A la lista &quot;Algún día/Quizás&quot;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;3. Revisar y Poner al Día el Sistema:&lt;/h3&gt;
&lt;p&gt;Esta es la parte clave de mantenimiento. Reviso mis listas y mi calendario:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Calendario Pasado:&lt;/strong&gt; Miro rápido la semana que acaba. ¿Qué reuniones tuve? ¿Qué tareas hice? ¿Quedó algo pendiente para reprogramar o seguir? A veces esto me recuerda cosas que olvidé apuntar.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Calendario Futuro:&lt;/strong&gt; Miro la semana que viene (o las dos siguientes). ¿Qué citas, eventos o entregas importantes tengo? ¿Necesito preparar algo? ¿Reservar tiempo para alguna tarea gorda?&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Lista de &quot;Próximas Acciones&quot;:&lt;/strong&gt; Reviso &lt;strong&gt;CADA&lt;/strong&gt; acción de mi lista.
&lt;ul&gt;
&lt;li&gt;¿Sigue teniendo sentido? (Igual algo ha cambiado).&lt;/li&gt;
&lt;li&gt;¿Es de verdad la &lt;em&gt;siguiente&lt;/em&gt; cosa física y concreta que hay que hacer? (Ej: &quot;Buscar info sobre librería X&quot; es mejor que &quot;Hacer login&quot;).&lt;/li&gt;
&lt;li&gt;¿Está claro lo que hay que hacer? ¿Necesito más info?&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Opcional:&lt;/em&gt; Reviso por contextos si los uso (&lt;code&gt;@ordenador&lt;/code&gt;, &lt;code&gt;@oficina&lt;/code&gt;, &lt;code&gt;@casa&lt;/code&gt;, &lt;code&gt;@llamadas&lt;/code&gt;, &lt;code&gt;@email&lt;/code&gt;, &lt;code&gt;@dev&lt;/code&gt;). Ayuda a ver qué puedo hacer según dónde esté o qué tenga a mano.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Lista de &quot;Proyectos&quot;:&lt;/strong&gt; Reviso &lt;strong&gt;CADA&lt;/strong&gt; proyecto activo (trabajo y personal). Un &quot;proyecto&quot; en GTD es cualquier cosa que necesite más de una acción (Ej: &quot;Lanzar v2.1&quot;, &quot;Aprender Go&quot;, &quot;Preparar charla&quot;, &quot;Planificar vacaciones&quot;). Para cada proyecto, me aseguro de que:
&lt;ul&gt;
&lt;li&gt;El &lt;strong&gt;estado&lt;/strong&gt; es correcto (Activo, Pausado, Terminado).&lt;/li&gt;
&lt;li&gt;Tiene &lt;strong&gt;al menos una &quot;Próxima Acción&quot; definida&lt;/strong&gt; en mi lista. ¡Esto es CLAVE para que los proyectos no se queden parados!&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Lista &quot;A la Espera&quot;:&lt;/strong&gt; Reviso las cosas que he pasado a otros o que estoy esperando que me lleguen (Ej: &quot;Esperando respuesta de Menganito al PR&quot;, &quot;Esperando que aprueben presupuesto para licencia&quot;). ¿Tengo que preguntar qué pasa? ¿Ha llegado ya y puedo tacharlo?&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Checklists (si uso):&lt;/strong&gt; Reviso checklists para tareas repetitivas (Ej: &quot;Pasos para publicar post&quot;, &quot;Checklist antes de desplegar&quot;, &quot;Backup semanal&quot;). ¿He hecho los pasos de esta semana?&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;4. Mirar Hacia Adelante y Ser Creativo:&lt;/h3&gt;
&lt;p&gt;Cuando el sistema está limpio y al día, dedico unos minutos a pensar más en grande:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Lista &quot;Algún día/Quizás&quot;:&lt;/strong&gt; Le echo un ojo rápido. ¿Hay alguna idea o proyecto aparcado que me apetezca empezar ahora? ¿Algo que ya no me interesa y puedo borrar?&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Brainstorming Libre:&lt;/strong&gt; Esto es opcional, pero útil. A veces dejo la mente volar: ¿Cómo podría mejorar esto? ¿Qué &lt;em&gt;side-project&lt;/em&gt; nuevo me molaría? ¿Qué tecnología quiero mirar? Apunto cualquier idea interesante (quizás en un sitio específico de mi app de notas o tareas).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Definir Objetivos/Tareas Clave para la Semana Entrante:&lt;/strong&gt; Viendo los proyectos y el calendario, elijo 2-3 prioridades o tareas importantes en las que quiero centrarme la semana que viene. No es un plan cerrado, es una intención.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Mis Herramientas Clave en Acción Durante la Revisión&lt;/h2&gt;
&lt;p&gt;Puedes usar GTD con cualquier herramienta, pero tener las adecuadas y saber usarlas ayuda mucho. Este es mi equipo actual:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Mi Gestor de Tareas Principal (Todoist)&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Uso en la Revisión:&lt;/strong&gt; &lt;code&gt;Todoist&lt;/code&gt; es mi centro de mando para las tareas. Su simplicidad y potencia con filtros y etiquetas son clave. En la revisión:
&lt;ul&gt;
&lt;li&gt;Vacío el &lt;code&gt;Inbox&lt;/code&gt; procesando cada tarea como expliqué antes.&lt;/li&gt;
&lt;li&gt;Uso &lt;strong&gt;Filtros&lt;/strong&gt; personalizados para revisar las &lt;code&gt;Próximas Acciones&lt;/code&gt; por contexto (&lt;code&gt;@work&lt;/code&gt;, &lt;code&gt;@personal&lt;/code&gt;, &lt;code&gt;@dev&lt;/code&gt;, &lt;code&gt;@email&lt;/code&gt;, etc.) o según prioridades y fechas. Un filtro típico podría ser &lt;code&gt;(hoy | próximos 7 días | sin fecha) &amp;amp; !@espera&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Reviso la lista de &lt;code&gt;Proyectos&lt;/code&gt;, asegurándome de que cada uno tiene al menos una próxima acción definida y está activo o archivado según corresponda. A veces uso secciones dentro de los proyectos para organizarlos mejor.&lt;/li&gt;
&lt;li&gt;Reviso mi filtro o etiqueta de &lt;code&gt;@espera&lt;/code&gt; para las tareas delegadas o pendientes de otros.&lt;/li&gt;
&lt;li&gt;Reviso mi proyecto o etiqueta &lt;code&gt;Algún día/Quizás&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Estructura:&lt;/strong&gt; Organizo todo con &lt;code&gt;Proyectos&lt;/code&gt; (para los resultados grandes) y &lt;code&gt;Etiquetas&lt;/code&gt; (para los contextos: &lt;code&gt;@work&lt;/code&gt;, &lt;code&gt;@personal&lt;/code&gt;, &lt;code&gt;@email&lt;/code&gt;, &lt;code&gt;@llamada&lt;/code&gt;, &lt;code&gt;@dev&lt;/code&gt;, &lt;code&gt;@espera&lt;/code&gt;, &lt;code&gt;@someday&lt;/code&gt;...). Asigno &lt;code&gt;Fechas de Vencimiento&lt;/code&gt; solo cuando son límites reales, no para todo.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Mi Calendario (Notion Calendar)&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Uso en la Revisión:&lt;/strong&gt; Lo uso para lo que tiene fecha y hora: reuniones, citas, eventos. Y muy importante: en la revisión, &lt;strong&gt;reservo tiempo&lt;/strong&gt; para tareas gordas de la semana siguiente. Por ejemplo, bloqueo 2 horas el martes por la mañana para &quot;Deep Work: Refactorizar Módulo X&quot; o 1 hora el jueves para &quot;Estudiar API Y&quot;. Esto protege mi tiempo de concentración. Reviso la semana pasada y las dos siguientes al &quot;Revisar Calendario&quot;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Mi Sistema de Notas/Referencia (Notion)&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Uso en la Revisión:&lt;/strong&gt; Aquí guardo el material de apoyo: notas de reuniones, trozos de código, resúmenes, ideas, checklists... En la revisión, si necesito consultar algo para una tarea o proyecto, abro &lt;code&gt;Notion&lt;/code&gt;. Los enlaces entre notas son geniales para conectar ideas. También tengo una nota &quot;Ideas Semanales&quot; donde apunto lo que sale en el paso 4.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;(Opcional) Integración con Herramientas de Desarrollo:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;¿Issues de GitHub/GitLab, Tareas de Jira/Azure DevOps?&lt;/strong&gt; Hay varias formas de manejar esto. Puedes revisar estas herramientas por separado durante tu revisión semanal, o puedes crear tareas en tu sistema principal (&lt;code&gt;Notion&lt;/code&gt;, &lt;code&gt;Todoist&lt;/code&gt;, etc.) que enlacen a los issues o tickets importantes que requieran una acción concreta por tu parte (más allá de &quot;mirar el ticket&quot;). Elige el método que mejor te funcione para no duplicar trabajo pero tampoco perder de vista tus tareas de desarrollo.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Consejos Específicos para la Rutina GTD de un Desarrollador&lt;/h2&gt;
&lt;p&gt;El GTD vale para todo, pero como desarrolladores, tenemos nuestras cosas:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Bugs e Incidencias:&lt;/strong&gt; ¿Cómo encajan? Depende. Un bug crítico puede ser una &quot;próxima acción&quot; inmediata (&quot;Investigar error 500 ya&quot;). Uno menos urgente, una tarea dentro de su proyecto (&quot;Corregir bug #456&quot;). Si arreglarlo lleva varios pasos, ¡es un mini-proyecto! La clave es apuntarlo y decidir qué hacer al procesar.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Aprendizaje Continuo:&lt;/strong&gt; ¡Vital! Trátalo como un proyecto más. Ten un proyecto &quot;Aprender&quot; o específicos (&quot;Aprender GraphQL&quot;, &quot;Dominar Docker&quot;). Asegúrate de que siempre tengan una &quot;próxima acción&quot; (&quot;Ver vídeo curso X&quot;, &quot;Hacer tutorial Y&quot;, &quot;Leer capítulo 3&quot;). En la revisión, mira si le dedicas tiempo y resérvalo en el calendario si hace falta.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Cambiar de Contexto (Context Switching):&lt;/strong&gt; Separar curro y proyectos personales es difícil. Usar contextos (&lt;code&gt;@work&lt;/code&gt;, &lt;code&gt;@personal&lt;/code&gt;) ayuda. En la revisión, puedes mirar primero lo del trabajo y luego lo personal. Ser consciente de los límites y proteger tiempo para cada cosa es clave. La revisión te ayuda a ver si un área se está comiendo el tiempo de la otra.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Proyectos Largos/Complejos:&lt;/strong&gt; La revisión semanal es tu mejor amiga aquí. Al revisar &lt;em&gt;cada&lt;/em&gt; proyecto &lt;em&gt;cada&lt;/em&gt; semana y asegurarte de que &lt;em&gt;siempre&lt;/em&gt; tiene una &quot;próxima acción&quot;, evitas que se paren o te agobien. Aunque solo des un pequeño paso cada semana, el proyecto sigue vivo. Dividir el proyecto en fases más pequeñas también ayuda.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Conclusión (Cierre y Llamada a la Acción)&lt;/h2&gt;
&lt;p&gt;Hacer una revisión semanal GTD ha sido una de las mejores cosas que he hecho para mi organización como desarrollador. Me ha devuelto la sensación de control en medio del caos típico de nuestro trabajo, me ha aclarado las prioridades y ha bajado mucho mi nivel de estrés. Ya no siento que se me escapan las cosas.&lt;/p&gt;
&lt;p&gt;Quiero que te quedes con esto: la revisión semanal &lt;strong&gt;no es un trámite más&lt;/strong&gt;, es la &lt;strong&gt;inversión&lt;/strong&gt; que hace que todo lo demás funcione mejor durante la semana. Es como el mantenimiento de tu sistema personal de productividad.&lt;/p&gt;
&lt;p&gt;Por supuesto, este es &lt;em&gt;mi&lt;/em&gt; sistema. Lo más importante es que &lt;strong&gt;pruebes, adaptes y encuentres lo que te funciona a ti&lt;/strong&gt;. Prueba herramientas, cambia el momento de tu revisión, ajusta los pasos. ¡No hay una única forma correcta! Lo que importa es ser constante y seguir las ideas principales.&lt;/p&gt;
</content:encoded></item><item><title>3 herramientas que me están ayudando a ser más productivo como desarrollador</title><link>https://franmoreno.com/blog/3-herramientas-desarrollo-fullstack-2025/</link><guid isPermaLink="true">https://franmoreno.com/blog/3-herramientas-desarrollo-fullstack-2025/</guid><pubDate>Thu, 17 Apr 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Estos meses estoy a tope desarrollando un SaaS de gestión para hostelería y como siempre, trasteando con ideas y mejoras para mi web personal. Para no volverme loco entre contextos, clientes y código, me apoyo en algunas herramientas que me están haciendo la vida más fácil.&lt;/p&gt;
&lt;p&gt;No son las únicas que uso, pero sí las que más están marcando la diferencia en mi flujo de trabajo actual.&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;🧱 1. &lt;a href=&quot;https://nextjs.org/&quot;&gt;Next.js&lt;/a&gt; – Productividad desde el minuto uno&lt;/h2&gt;
&lt;p&gt;Next.js se ha convertido en mi framework principal para casi todo lo que implica desarrollo fullstack. Lo uso para casi cualquier proyecto y la verdad es que me permite montar webs robustas sin perder tiempo en configuración.&lt;/p&gt;
&lt;p&gt;Entre las rutas con app router, el sistema de APIs integrado, y la posibilidad de hacer SSR o ISR según lo que necesites tengo todo lo que necesito. Me da estructura sin limitarme.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Si quieres profundizar en por qué elijo Next.js (y cuándo prefiero Astro), puedes leer &lt;a href=&quot;/blog/experiencia-nextjs-vs-astro-proyectos-personales/&quot;&gt;mi comparativa aquí&lt;/a&gt;&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Y lo mejor: puedo centrarme en el producto, no en reinventar la rueda cada vez.&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;🗃️ 2. &lt;a href=&quot;https://supabase.com/&quot;&gt;Supabase&lt;/a&gt; – Backend sin fricciones&lt;/h2&gt;
&lt;p&gt;La segunda pata de mi stack ahora mismo es Supabase. Es la base de datos, el sistema de autenticación y la API REST de mi proyecto, todo en uno. Y además, sin necesidad de montar nada por mi cuenta, ni gestionar servidores.&lt;/p&gt;
&lt;p&gt;Lo que más valoro es poder hacer pruebas rápidas, tener una base de datos PostgreSQL real detrás y una interfaz web decente para gestionarlo todo. Para proyectos que necesitan escalar más adelante, pero empezar ya, es ideal.&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;🤖 3. &lt;a href=&quot;https://www.cursor.so/&quot;&gt;Cursor&lt;/a&gt; – Un IDE con IA que de verdad ayuda&lt;/h2&gt;
&lt;p&gt;He probado muchos editores y asistentes de IA, pero &lt;a href=&quot;https://www.cursor.so/&quot;&gt;Cursor&lt;/a&gt; es el que más me ha convencido. Está basado en VS Code, pero mejor integrado con IA para cosas muy concretas del día a día: modificar un archivo según un prompt, generar código a partir del contexto del proyecto, revisar carpetas enteras…&lt;/p&gt;
&lt;p&gt;Es como tener un becario superdotado que realmente entiende lo que estás haciendo, y no solo te sugiere código al azar. Incluso puedo seleccionar una función y decirle &quot;hazlo más limpio&quot; o &quot;añade tests&quot; y me saca algo útil el 90% de las veces.&lt;/p&gt;
&lt;p&gt;Está claro que no funciona por si solo, y a veces se lía, tienes que darle pistas, pero la productividad que añade es enorme.&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;💬 En resumen&lt;/h2&gt;
&lt;p&gt;Lo que me importa no es tener un stack enorme, sino uno que me quite trabajo de encima. Estas tres herramientas —Next.js, Supabase y Cursor— me están ayudando justo con eso: construir más rápido, con menos fricción y sin perder calidad.&lt;/p&gt;
</content:encoded></item><item><title>Introducción a Cloudflare Workers</title><link>https://franmoreno.com/blog/introduccion-a-cloudflare-workers/</link><guid isPermaLink="true">https://franmoreno.com/blog/introduccion-a-cloudflare-workers/</guid><pubDate>Wed, 15 May 2024 14:12:53 GMT</pubDate><content:encoded>&lt;h2&gt;¿Qué son los Cloudflare Workers?&lt;/h2&gt;
&lt;p&gt;Cloudflare Workers es una plataforma de computación serverless que permite a los desarrolladores ejecutar código JavaScript en los servidores de Cloudflare distribuidos globalmente. Esto significa que puedes ejecutar tu lógica de aplicación más cerca de tus usuarios finales, reduciendo significativamente la latencia y mejorando el rendimiento general de tu sitio web o aplicación.&lt;/p&gt;
&lt;h2&gt;¿Cómo Funcionan los Cloudflare Workers?&lt;/h2&gt;
&lt;p&gt;Los Cloudflare Workers se basan en el estándar de la WebAssembly (WASM), lo que les permite ejecutar código con gran eficiencia y seguridad. Aquí tienes un desglose de cómo funcionan:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Distribución Global&lt;/strong&gt;: Cloudflare tiene una red global con más de 200 centros de datos. Cuando despliegas un Worker, tu código se replica en todos estos centros de datos. &lt;em&gt;Este mismo principio es el que aprovecha &lt;a href=&quot;/blog/moviendo-mis-side-projects-a-cloudflare/&quot;&gt;Cloudflare Pages&lt;/a&gt; para servir sitios estáticos rápidamente.&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Ejecución en el Borde&lt;/strong&gt;: En lugar de enviar todas las solicitudes a un servidor central, los Workers procesan las solicitudes en el servidor más cercano al usuario, mejorando la velocidad de respuesta.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Escalabilidad Automática&lt;/strong&gt;: Los Workers escalan automáticamente para manejar cualquier cantidad de tráfico sin necesidad de que te preocupes por la infraestructura.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;Beneficios de Usar Cloudflare Workers&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Rendimiento Mejorado&lt;/strong&gt;: Al ejecutar código en el borde, los tiempos de respuesta se reducen drásticamente.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Seguridad&lt;/strong&gt;: Los Workers permiten implementar lógica de seguridad como controles de acceso y validación de datos directamente en el borde.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Escalabilidad y Flexibilidad&lt;/strong&gt;: Cloudflare se encarga de la escalabilidad, permitiéndote concentrarte en el desarrollo de tu aplicación.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Coste Reducido&lt;/strong&gt;: Al ser una solución serverless, solo pagas por las invocaciones de tu código, eliminando los costos asociados con servidores siempre activos.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;Casos de Uso Comunes&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Redirección de Tráfico&lt;/strong&gt;: Redirige a los usuarios a diferentes versiones de tu sitio web según su ubicación geográfica.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Optimización de Imágenes&lt;/strong&gt;: Procesa y optimiza imágenes en el borde para mejorar los tiempos de carga.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Autenticación y Autorización&lt;/strong&gt;: Implementa mecanismos de autenticación y autorización directamente en el borde para mejorar la seguridad.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Primeros Pasos con Cloudflare Workers&lt;/h2&gt;
&lt;p&gt;A continuación, los pasos que tienes que dar para empezar con Cloudflare Workers directamente desde el panel de Cloudflare:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Registro y Configuración&lt;/strong&gt;: Regístrate en Cloudflare (si es que no lo has hecho ya...) y añade tu dominio. En el panel de control, navega hasta la sección de Workers.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Crear un Worker&lt;/strong&gt;: Haz clic en &quot;Crear un Worker&quot;. Cloudflare te proporcionará una interfaz para escribir y probar tu código.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Escribir Código&lt;/strong&gt;: Utiliza JavaScript para escribir tu lógica. Por ejemplo, un Worker sencillo para responder con un mensaje &quot;Hello World&quot; se vería así:&lt;/li&gt;
&lt;/ol&gt;
&lt;pre&gt;&lt;code&gt;addEventListener(&apos;fetch&apos;, (event) =&amp;gt; {
  event.respondWith(handleRequest(event.request))
})

async function handleRequest(request) {
  return new Response(&apos;Hello World&apos;, {
    headers: { &apos;content-type&apos;: &apos;text/plain&apos; }
  })
}
&lt;/code&gt;&lt;/pre&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Desplegar&lt;/strong&gt;: Una vez que estés satisfecho con tu código, puedes desplegar el Worker y comenzará a ejecutarse en la red global de Cloudflare.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;Usando Wrangler para crear y desplegar workers&lt;/h2&gt;
&lt;h3&gt;Paso 1: Instalación de Wrangler&lt;/h3&gt;
&lt;p&gt;Primero, necesitas instalar Wrangler. Asegúrate de tener Node.js y npm instalados en tu sistema. Luego, ejecuta el siguiente comando en tu terminal para instalar Wrangler globalmente:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;npm install -g @cloudflare/wrangler
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Paso 2: Configuración de Wrangler&lt;/h3&gt;
&lt;p&gt;Una vez instalado, debes configurar Wrangler con tus credenciales de Cloudflare. Ejecuta el siguiente comando para iniciar sesión:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;wrangler login
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Esto abrirá una ventana del navegador donde podrás iniciar sesión en tu cuenta de Cloudflare y autorizar a Wrangler.&lt;/p&gt;
&lt;h3&gt;Paso 3: Crear un Proyecto de Worker&lt;/h3&gt;
&lt;p&gt;Con Wrangler configurado, puedes crear un nuevo proyecto de Worker. Usa el siguiente comando para generar un proyecto básico:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;wrangler generate my-first-worker
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Este comando creará un directorio llamado my-first-worker con una plantilla básica de Worker.&lt;/p&gt;
&lt;h3&gt;Paso 4: Modificar el Código del Worker&lt;/h3&gt;
&lt;p&gt;Navega al directorio del proyecto recién creado y abre el archivo index.js en tu editor de texto favorito. Aquí es donde puedes escribir la lógica de tu Worker. Por ejemplo, para responder con un mensaje &quot;Hello World&quot; podemos usar el mismo código del principio del artículo.&lt;/p&gt;
&lt;h3&gt;Paso 5: Prueba Local&lt;/h3&gt;
&lt;p&gt;Wrangler permite probar tu Worker localmente antes de desplegarlo. Usa el siguiente comando para iniciar el entorno de desarrollo local:&lt;/p&gt;
&lt;p&gt;Esto iniciará un servidor local y te proporcionará una URL donde puedes probar tu Worker en tu navegador.&lt;/p&gt;
&lt;h3&gt;Paso 6: Desplegar el Worker&lt;/h3&gt;
&lt;p&gt;Una vez que estés satisfecho con tu Worker, puedes desplegarlo a la red global de Cloudflare. Ejecuta el siguiente comando para desplegar tu Worker:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;wrangler publish
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Wrangler subirá tu código a Cloudflare y lo desplegará en todos sus centros de datos. Recibirás una URL donde tu Worker estará disponible.&lt;/p&gt;
&lt;h3&gt;Paso 7: Configuración Adicional&lt;/h3&gt;
&lt;p&gt;Puedes configurar más aspectos de tu Worker, como el nombre, el dominio y las variables de entorno, editando el archivo wrangler.toml generado en tu proyecto. Este archivo permite personalizar la configuración y el comportamiento de tu Worker.&lt;/p&gt;
</content:encoded></item><item><title>Moviendo mis side projects a Cloudflare</title><link>https://franmoreno.com/blog/moviendo-mis-side-projects-a-cloudflare/</link><guid isPermaLink="true">https://franmoreno.com/blog/moviendo-mis-side-projects-a-cloudflare/</guid><pubDate>Mon, 13 May 2024 09:24:48 GMT</pubDate><content:encoded>&lt;p&gt;Desde hace tiempo vengo usando Vercel para el despliegue de mis proyectos frontend (sigo usándolo) pero últimamente estoy migrando algunos de los proyectos en los que estoy trabajando al entorno Cloudflare, usando tanto Cloudflare Pages como &lt;a href=&quot;https://workers.cloudflare.com/&quot;&gt;Cloudflare Workers&lt;/a&gt; (sobre los que puedes leer &lt;a href=&quot;/blog/introduccion-a-cloudflare-workers/&quot;&gt;una introducción aquí&lt;/a&gt;) y estoy muy contento.&lt;/p&gt;
&lt;p&gt;En este artículo, exploraremos las ventajas de Cloudflare Pages respecto a Vercel.&lt;/p&gt;
&lt;h2&gt;Mayor rendimiento y velocidad&lt;/h2&gt;
&lt;p&gt;Una de las principales ventajas de Cloudflare Pages es su red de distribución de contenido (CDN) global. Al aprovechar esta red, nuestros proyectos se beneficiarán de una mayor velocidad de carga y rendimiento, ya que los archivos se servirán desde el servidor más cercano al usuario.&lt;/p&gt;
&lt;h2&gt;Escalabilidad y disponibilidad&lt;/h2&gt;
&lt;p&gt;Cloudflare Pages ofrece una infraestructura escalable y altamente disponible. Esto significa que nuestros proyectos podrán manejar un mayor volumen de tráfico sin comprometer la estabilidad o la experiencia del usuario. Además, Cloudflare cuenta con una arquitectura distribuida que garantiza la disponibilidad de nuestros proyectos en caso de fallos en un servidor o región específica.&lt;/p&gt;
&lt;p&gt;Además de la escalabilidad y disponibilidad, Cloudflare Pages también ofrece otras características que pueden mejorar aún más nuestros proyectos. Por ejemplo, podemos aprovechar la capacidad de caché de Cloudflare para almacenar en caché el contenido estático de nuestros sitios web, lo que reduce la carga en nuestros servidores y mejora la velocidad de carga para los usuarios.&lt;/p&gt;
&lt;p&gt;Cloudflare Pages también nos permite personalizar la configuración de DNS para nuestros proyectos, lo que nos brinda un mayor control sobre la gestión de los nombres de dominio y la resolución de DNS. Esto puede ser especialmente útil si necesitamos configurar redirecciones, subdominios o registros DNS específicos.&lt;/p&gt;
&lt;h2&gt;Integración con otros servicios de Cloudflare&lt;/h2&gt;
&lt;p&gt;Otra ventaja de migrar a Cloudflare Pages es la integración con otros servicios de Cloudflare. Podremos aprovechar características como la protección contra ataques DDoS, el firewall de aplicaciones web (WAF) y la optimización de imágenes, entre otros. Esto nos permitirá mejorar la seguridad y el rendimiento de nuestros proyectos sin tener que implementar soluciones adicionales.&lt;/p&gt;
&lt;h2&gt;Costes reducidos&lt;/h2&gt;
&lt;p&gt;Cloudflare Pages ofrece un plan gratuito generoso que incluye un alto límite de ancho de banda y almacenamiento. Esto puede resultar en costos reducidos en comparación con Vercel u otras plataformas de alojamiento. Además, Cloudflare ofrece planes de precios flexibles que se adaptan a las necesidades de nuestros proyectos a medida que crecen.&lt;/p&gt;
&lt;h2&gt;Desventajas&lt;/h2&gt;
&lt;p&gt;Obviamente, no todo puede ser perfecto, sobre todo si trabajamos con &lt;a href=&quot;https://nextjs.org/&quot;&gt;NextJS&lt;/a&gt;, Vercel ofrece mucho mejor soporte para este Framework (lo han desarrollado ellos...) por lo que algunas de las ventajas y novedades que ofrecen no estarán disponibles cuando despliegas un proyecto con Cloudflare Pages, pero para la mayoría de proyectos es una solución más que interesante.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;🚀 ¿Migrando un Next.js a Cloudflare?&lt;/strong&gt; La parte que más fricción me dio al mover proyectos fue la configuración inicial: &lt;code&gt;@opennextjs/cloudflare&lt;/code&gt;, autenticación, base de datos y CI/CD. He empaquetado todo eso en el &lt;a href=&quot;https://fransiner.gumroad.com/l/nextjs-cloudflare-starter-auth-database-edge-deploy&quot;&gt;&lt;strong&gt;Next.js + Cloudflare Pages Starter Kit&lt;/strong&gt;&lt;/a&gt; — Better Auth, Drizzle + Supabase, GitHub Actions y deploy automático. De cero a desplegado en ~30 minutos.&lt;/p&gt;
&lt;/blockquote&gt;
</content:encoded></item><item><title>Objetivos personales y profesionales para 2023</title><link>https://franmoreno.com/blog/objetivos-personales-y-profesionales-2023/</link><guid isPermaLink="true">https://franmoreno.com/blog/objetivos-personales-y-profesionales-2023/</guid><pubDate>Sat, 17 Dec 2022 09:30:42 GMT</pubDate><content:encoded>&lt;p&gt;Una de las cosas que empecé a hacer desde que uso &lt;a href=&quot;https://franmoreno.com/blog/gestionar-vida-notion-metodologia-gtd/&quot;&gt;GTD como mi sistema de gestión&lt;/a&gt; de tareas es establecer objetivos, para tener una visión de alto nivel de lo que quiero hacer en mi vida y en mi carrera profesional. &lt;em&gt;Mi &lt;a href=&quot;/blog/flujo-gtd-semanal-desarrollador/&quot;&gt;flujo semanal GTD&lt;/a&gt; me ayuda a revisar y mantener estos objetivos.&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;Objetivos cumplidos 2021-2022&lt;/h2&gt;
&lt;p&gt;La última vez que me planteé objetivos tecnológicos fue en 2021, &lt;a href=&quot;https://franmoreno.com/blog/web-development-technologies-learn-2021/&quot;&gt;en este artículo&lt;/a&gt;, de los cuales cumplí dos (&lt;strong&gt;React&lt;/strong&gt; y &lt;strong&gt;Tailwind&lt;/strong&gt;), uno lo cumplí a medias (en lugar de aprender &lt;strong&gt;frontity&lt;/strong&gt; acabé montando un proyecto que atacaba a un &lt;strong&gt;WordPress&lt;/strong&gt; directamente usando &lt;strong&gt;GraphQL&lt;/strong&gt; desde &lt;strong&gt;NextJS&lt;/strong&gt;, porque me daba más flexibilidad para trabajar a mi gusto) y finalmente no dediqué nada de tiempo a aprender &lt;strong&gt;InertiaJS&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Otro de los objetivos tecnológicos que me propuse fue rehacer mi web y mi blog, además de lanzar un proyecto personal basado en alguno de mis hobbies (&lt;a href=&quot;https://torneospokerlive.com/&quot;&gt;Torneos Poker España&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;También me propuse empezar a hacer más ejercicio, desde marzo de 2020 (a saber qué pasó en esa época…) dejé de hacer deporte de forma continua, hasta esa fecha jugaba semanalmente mi partido de fútbol sala, algún partido de tenis o pádel, iba andando al trabajo a diario… Desde entonces, no volví a jugar mi partido semanal, dejé de ir andando a la oficina (me mudé) y empecé a teletrabajar.&lt;/p&gt;
&lt;p&gt;Desde septiembre de este año estoy haciendo ejercicio (&lt;strong&gt;Crossfit&lt;/strong&gt;), andando una media de 30 minutos diarios y comiendo algo más sano. Con esto he conseguido, además de bajar unos kilos de peso, sentirme mejor física y mentalmente.&lt;/p&gt;
&lt;h2&gt;Objetivos profesionales&lt;/h2&gt;
&lt;p&gt;Para este año que empieza en breve tengo dos objetivos principales a nivel profesional:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Aprender a desarrollar aplicaciones con &lt;a href=&quot;https://ionicframework.com/&quot;&gt;Ionic&lt;/a&gt; + &lt;a href=&quot;https://capacitorjs.com/&quot;&gt;Capacitor&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Aprender &lt;a href=&quot;https://jestjs.io/es-ES/&quot;&gt;Jest&lt;/a&gt; y mejorar en &lt;strong&gt;TDD&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Respecto al primero de ellos, ya he hecho alguna aplicación con Ionic, pero hasta ahora me he quedado en un nivel muy básico y quiero mejorar el proceso.&lt;/p&gt;
&lt;h2&gt;Objetivos personales&lt;/h2&gt;
&lt;p&gt;A nivel personal, tengo tres frentes a cubrir:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Mejorar mi estado físico.&lt;/li&gt;
&lt;li&gt;Leer más&lt;/li&gt;
&lt;li&gt;Compartir más contenido online (este blog, un podcast…)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Para conseguir el primero de los objetivos seguiré entrenando mínimo 3 días semanales y seguiré cuidando mi dieta. La lectura es un punto débil que tengo desde hace mucho tiempo, no soy muy buen lector, suelo abandonar los libros a mitad y no terminan de engancharme.&lt;/p&gt;
&lt;p&gt;Este artículo intenta hacer posible que cumpla el tercero de ellos, &lt;strong&gt;compartir más contenido&lt;/strong&gt;, ya sea en este blog o incluso volver a hacer algo relacionado con el podcasting (desde que dejamos de publicar el podcast &lt;a href=&quot;https://necesitounarma.com/&quot;&gt;Necesito un Arma&lt;/a&gt; tengo bastantes ganas de volver a las andadas)&lt;/p&gt;
</content:encoded></item><item><title>Gestionar tu vida con Notion y la metodología GTD</title><link>https://franmoreno.com/blog/gestionar-vida-notion-metodologia-gtd/</link><guid isPermaLink="true">https://franmoreno.com/blog/gestionar-vida-notion-metodologia-gtd/</guid><pubDate>Wed, 14 Dec 2022 09:29:53 GMT</pubDate><content:encoded>&lt;p&gt;Desde que tengo uso de razón me he considerado una persona &lt;strong&gt;más o menos organizada&lt;/strong&gt;, que suele acordarse de las reuniones y fechas importantes, que puede llevar a cabo proyectos de medio y largo plazo sin muchos problemas y que puede gestionarse medio bien. Pero no siempre todo sale tan fácil como nos gustaría, no siempre cumplimos los plazos y no siempre tenemos todo bajo control.&lt;/p&gt;
&lt;p&gt;En los últimos 15 años, tanto trabajando por cuenta ajena, como en &lt;a href=&quot;https://www.sozpic.com&quot;&gt;Sozpic&lt;/a&gt; como CEO y CTO, tuve la necesidad de organizar (no siempre lo hice bien, por supuesto…)&lt;/p&gt;
&lt;p&gt;Hubo un &lt;strong&gt;punto de inflexión&lt;/strong&gt; durante los meses de marzo y abril de 2020, cuando acabamos todos encerrados en casa. Creo que no fui solo yo, que hubo más gente afectada por esto, pero me vi en la necesidad de poner orden en la forma de gestionar todo en la empresa y por extensión en mi vida.&lt;/p&gt;
&lt;h2&gt;Un sistema&lt;/h2&gt;
&lt;p&gt;Entonces entendí que lo más importante para poder organizarse bien es tener un buen sistema, un sistema robusto, que se adapte bien a ti y que pueda albergar todas tus necesidades de gestión y organización. Ahí descubrí el sistema &lt;a href=&quot;https://es.wikipedia.org/wiki/Getting_Things_Done&quot;&gt;GTD&lt;/a&gt; (&lt;strong&gt;Getting Things Done&lt;/strong&gt;) de David Allen.&lt;/p&gt;
&lt;p&gt;El sistema GTD tiene como objetivo liberar tu mente de tareas recurrentes que se pasean en bucle hasta que las haces, para eso se basa en &lt;strong&gt;5 principios&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Recopilar&lt;/strong&gt;: Todo lo que te pase por la cabeza en algún momento lo lanzas al sistema&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Procesar&lt;/strong&gt;: Decides qué es lo que has ido recopilado (una tarea, un proyecto, una llamada, un recordatorio…)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Organizar&lt;/strong&gt;: Pones cada cosa en su sitio (le pones fecha si es necesario, añades información relevante, lo contextualizas, lo añades a un proyecto existente…)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Revisar&lt;/strong&gt;: Repasas cada cierto tiempo que todo esté en orden, haces ajustes necesarios en el sistema.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Hacer&lt;/strong&gt;: Te pones a trabajar, con todo bien organizado y cada cosa en su sitio.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Y define el proceso que debes seguir para que todo este engranaje funcione bien:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/blog/gtd.jpg&quot; alt=&quot;Proceso GTD&quot; /&gt;&lt;/p&gt;
&lt;h2&gt;Vale, ahora tengo que poner todo esto en algún sitio&lt;/h2&gt;
&lt;p&gt;David Allen cuando explica la metodología insiste en que no depende de ninguna herramienta, es decir, podría hacerse con papel y bolígrafo. Pero estamos en el siglo XXI y ya nadie usa papel y bolígrafo…&lt;/p&gt;
&lt;p&gt;La primera herramienta que usé para llevar todo mi sistema GTD fue &lt;a href=&quot;https://todoist.com/&quot;&gt;Todoist&lt;/a&gt;, me permitía organizar bien todo el sistema mediante proyectos, etiquetas, tareas, subtareas… pero siempre he echado en falta una parte importante de documentación y recursos relativos a los proyectos y tareas de GTD, que siempre tenía que irme a otra herramienta distinta a &lt;strong&gt;Todoist&lt;/strong&gt; (Google Drive, iCloud, etc…)&lt;/p&gt;
&lt;h2&gt;Notion&lt;/h2&gt;
&lt;p&gt;Notion como herramienta me permite, además de poder llevar al día mi sistema &lt;strong&gt;GTD&lt;/strong&gt; (tareas, proyectos, contextos, revisiones, etc…) tener también ahí toda la documentación necesaria, archivos de referencia…&lt;/p&gt;
&lt;p&gt;Si por ejemplo una tarea es escribir un artículo para el blog sobre &lt;strong&gt;GTD&lt;/strong&gt;, que ese artículo pueda ser un documento dentro de Notion enlazado con la tarea y que queda archivado en el sistema para revisarlo en el futuro.&lt;/p&gt;
&lt;p&gt;O por ejemplo, si una tarea consiste en preparar un documento de requisitos para un proyecto, este documento puede estar creado en &lt;strong&gt;Notion&lt;/strong&gt;, enlazado con la tarea o con el proyecto, modificarlo cuando quiera, exportarlo para enviarlo por email, imprimirlo… y todo sin salir de la herramienta con la que gestiono el sistema.&lt;/p&gt;
&lt;p&gt;Para implementar el sistema en &lt;strong&gt;Notion&lt;/strong&gt; me he ayudado de una serie de vídeos de &lt;a href=&quot;https://www.rubenloan.com/&quot;&gt;Rubén Loan&lt;/a&gt; (&lt;a href=&quot;https://www.youtube.com/watch?v=911ZGBQiKyc&amp;amp;list=PLWji3OEqhByRuAcNSpebAVG3mbNhGlPEm&quot;&gt;Serie de GTD y Notion&lt;/a&gt;) que me sirvieron para perder el miedo inicial a la herramienta (cómo empezar, cómo se crean secciones, bases de datos…)&lt;/p&gt;
&lt;p&gt;En otro artículo (este se está alargando más de la cuenta) explicaré con más detalle todo ese proceso, por si a alguien más le puede servir. &lt;em&gt;Puedes leer sobre mi flujo semanal GTD como desarrollador &lt;a href=&quot;/blog/flujo-gtd-semanal-desarrollador/&quot;&gt;aquí&lt;/a&gt;&lt;/em&gt;.&lt;/p&gt;
</content:encoded></item><item><title>Web development technologies I want to learn in 2021</title><link>https://franmoreno.com/blog/web-development-technologies-learn-2021/</link><guid isPermaLink="true">https://franmoreno.com/blog/web-development-technologies-learn-2021/</guid><pubDate>Sun, 07 Mar 2021 09:31:15 GMT</pubDate><content:encoded>&lt;p&gt;Last years I&apos;ve found myself reading about a lot of technologies and programming languages, understanding them, and knowing how to defend or write about them in technical proposals. But never digging into them and learning. It was ok for me with my long WordPress knowledge (more than 10 years working with WordPress, improving myself, and doing very interesting projects) and knowing Laravel at a medium level.&lt;/p&gt;
&lt;p&gt;But I want to learn more than this, I detected that I was so far to understand new technologies, new ways of work in web development (mostly frontend) and this year is going to be the gamechanger for me.&lt;/p&gt;
&lt;p&gt;Here is a list of web technologies and languages I want to learn (some of them I&apos;ve started and built some side projects)&lt;/p&gt;
&lt;h2&gt;English&lt;/h2&gt;
&lt;p&gt;I know this is not a programming language or a technology, but it is the most important skill every developer needs to know and improve. I&apos;m from Spain, so English is not my primary language, here in Spain is mandatory to study English in school until you go to the University, we are improving and learning more English than 20 years ago, but we still need to work on this.&lt;/p&gt;
&lt;p&gt;I think I have a good level, I can read, I can write (I&apos;m sure I have a lot of grammar fails) and I can maintain a conversation with different kind of English speakers around the world (last 10 years I&apos;ve spoken with people from Italy, Canada, USA, Israel, Germany, UK...) but I feel that I need to learn more.&lt;/p&gt;
&lt;p&gt;That&apos;s because I&apos;ve started writing my blog in English, to force myself to write and improve my language skills.&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;https://reactjs.org/&quot;&gt;Reactjs&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;That was my first choice to start learning a new programming language. I mostly know and understand VUE (not deep but can read code and do some little projects). A friend told me to help him with a project on &lt;a href=&quot;https://reactjs.org/&quot;&gt;Reactjs&lt;/a&gt; and that was the click I needed to start learning this.&lt;/p&gt;
&lt;p&gt;If you know Javascript and understand some simple programming concepts is a good language to learn, easy to start working (just start with &lt;a href=&quot;https://create-react-app.dev/&quot;&gt;create-react-app&lt;/a&gt; and you have a simple project to start playing)&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;https://tailwindcss.com/&quot;&gt;Tailwindcss&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I was a big defensor of Bootstrap, and still think that was a gamechanger, but every article or video I watch about Tailwindcss convinces me to take a shot.&lt;/p&gt;
&lt;p&gt;I think is the best way to work with HTML without thinking about CSS (at least at the beginning when you are doing some mockups) but every minute I work with this technology I understand that can be used to build a big project and can be improved to work in production.&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;https://frontity.org/&quot;&gt;Frontity&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;This is a React framework to work with WordPress, it allows you to use a WordPress instance to be your headless backend and build the frontend part using Reactjs. This is a very good way for me to start working with headless CMS (I&apos;m very confident with WordPress and is a very good CMS to work with)&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;https://inertiajs.com/&quot;&gt;Inertiajs&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I&apos;m interested in this project because is a good way to improve the two basic parts of a common web project (frontend part on react or VUE, backend part on Laravel or Rails)&lt;/p&gt;
&lt;p&gt;There are much more technologies and projects I want to dig into (Jamstack, Jest, ReactNative, StoryBook...) but I don&apos;t want to put myself in a rush or give me more pressure than I need.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;If you want to see how my stack has evolved, check out my thoughts on choosing between &lt;a href=&quot;/blog/experiencia-nextjs-vs-astro-proyectos-personales/&quot;&gt;Next.js (React-based) and Astro&lt;/a&gt; in 2025.&lt;/em&gt;&lt;/p&gt;
</content:encoded></item><item><title>Moss.sh, your virtual sysadmin</title><link>https://franmoreno.com/blog/moss-your-virtual-sysadmin/</link><guid isPermaLink="true">https://franmoreno.com/blog/moss-your-virtual-sysadmin/</guid><pubDate>Sat, 11 Jan 2020 09:30:13 GMT</pubDate><content:encoded>&lt;p&gt;Since I work as a web developer and deal with the Internet, I&apos;ve always been fighting with several hosting providers, dedicated servers, VPS, update installation, package management, PHP versions, security patches... Then I discover &lt;a href=&quot;https://moss.sh/?ref=b084ab56c373&quot;&gt;Moss.sh&lt;/a&gt;, and all these headaches disappeared, now it&apos;s like another step in the process, but not a problem to me.&lt;/p&gt;
&lt;p&gt;With &lt;a href=&quot;https://moss.sh/?ref=b084ab56c373&quot;&gt;Moss.sh&lt;/a&gt;, you only have to worry about two things, what is the server size you need to start and what is your stack or Framework (Laravel, WordPress, JS, HTML, PHP...), everything else is not your problem anymore.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/blog/h1Dtv85zh.png&quot; alt=&quot;Moss.sh&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Main characteristics:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Integration with DigitalOcean, Google Cloud, Amazon EC2 or Vultr&lt;/li&gt;
&lt;li&gt;You can manage all the Workspaces you need (and invite other users to them) to organize your servers and sites.&lt;/li&gt;
&lt;li&gt;Automatic deploys integrated with your favourite code management tool (Bitbucket, Github, GitLab…)&lt;/li&gt;
&lt;li&gt;Automatic server security updates.&lt;/li&gt;
&lt;li&gt;Easy management of Workers and Cronjobs for your servers and sites.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;And everything through a very easy interface. This tool was created by a good friend &lt;a href=&quot;https://twitter.com/danielvigueras&quot;&gt;Daniel Vigueras&lt;/a&gt; and his team.&lt;/p&gt;
</content:encoded></item><item><title>Comenzando con los Custom Post Types en WordPress</title><link>https://franmoreno.com/blog/comenzando-custom-post-types-wordpress/</link><guid isPermaLink="true">https://franmoreno.com/blog/comenzando-custom-post-types-wordpress/</guid><pubDate>Fri, 15 Feb 2019 09:29:33 GMT</pubDate><content:encoded>&lt;p&gt;Un aspecto importante en &lt;strong&gt;WordPress&lt;/strong&gt; son los &lt;a href=&quot;http://codex.wordpress.org/Function_Reference/register_post_type&quot;&gt;Custom Post Types&lt;/a&gt; , una característica que se incluyó a partir de la versión 3 de este CMS. Como la mayoría sabe, en WordPress hay varios tipos de posts nativos, los posts normales, como este artículo, una página estática, los archivos adjuntos (imágenes y demás) y las barras de navegación. Cada una de estas cosas tiene un tipo de post concreto en la tabla &lt;code&gt;wp_posts&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Desde la versión 3 se pueden definir Custom posts propios, lo que quiere decir que tenemos un montón de posibilidades de crear casi cualquier cosa que se nos ocurra. Para crear este tipo de posts se hace uso de la función &lt;code&gt;register_post_type&lt;/code&gt;, que paso a describir a continuación, creando un &lt;em&gt;Custom Post Type&lt;/em&gt; llamado &lt;strong&gt;Trabajo&lt;/strong&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    add_action(&apos;init&apos;, &apos;franmoreno_trabajos_register&apos;);

    function franmoreno_trabajos_register() {

        $labels = array(
            &apos;name&apos; =&amp;gt; __( &apos;Trabajos&apos; ),
            &apos;singular_name&apos; =&amp;gt; __( &apos;Trabajo&apos; ),
            &apos;add_new&apos; =&amp;gt; __( &apos;Añadir Nuevo&apos; ),
            &apos;add_new_item&apos; =&amp;gt; __( &apos;Añadir nuevo Trabajo&apos; ),
            &apos;edit_item&apos; =&amp;gt; __( &apos;Editar Trabajo&apos; ),
            &apos;new_item&apos; =&amp;gt; __( &apos;Nuevo Trabajo&apos;),
            &apos;view_item&apos; =&amp;gt; __( &apos;Ver Trabajo&apos;),
            &apos;search_items&apos; =&amp;gt; __( &apos;Buscar Trabajo&apos;),
            &apos;not_found&apos; =&amp;gt;  __(&apos;No se encontró nada&apos;),
            &apos;not_found_in_trash&apos; =&amp;gt; __(&apos;No se encontró nada en la papelera&apos;),
            &apos;parent_item_colon&apos; =&amp;gt; &apos;&apos;
        );

        $args = array(
            &apos;labels&apos; =&amp;gt; $labels,
            &apos;public&apos; =&amp;gt; true,
            &apos;rewrite&apos; =&amp;gt; true,
            &apos;capability_type&apos; =&amp;gt; &apos;post&apos;,
            &apos;hierarchical&apos; =&amp;gt; false,
            &apos;menu_position&apos; =&amp;gt; null,
            &apos;supports&apos; =&amp;gt; array(&apos;title&apos;,&apos;thumbnail&apos;,&apos;editor&apos;)
          );

        register_post_type( &apos;trabajos&apos; , $args );
    }
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Esta función recibe primero el nombre del &lt;em&gt;Custom Post&lt;/em&gt;, y segundo un array con los distintos argumentos para crearlo. Este array contiene los siguientes campos:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;labels&lt;/strong&gt;: Otro array con los distintos textos que se mostrarán en el panel de administración para gestionar nuestro &lt;em&gt;Custom Post Type&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;public&lt;/strong&gt;: Define si este &lt;em&gt;Custom Post&lt;/em&gt; es de acceso público o va a ser de uso interno.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;rewrite&lt;/strong&gt;: Define si se va a hacer uso de los &lt;em&gt;rewrites&lt;/em&gt; para generar &lt;em&gt;permalinks&lt;/em&gt; con este tipo de datos.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;capability_type&lt;/strong&gt;: Define la forma en la que se accederá a el internamente, en este caso, decimos que igual que un &lt;em&gt;post&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;hierarchical&lt;/strong&gt;: Permitimos que se asocien unos a otros como padres e hijos, &lt;em&gt;false&lt;/em&gt; es que no, comportándose como un post. Si decimos &lt;em&gt;true&lt;/em&gt;, se comportarán como páginas, pudiendo asignarles un padre.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;menu_position&lt;/strong&gt;: Definimos la posición que tendrá este &lt;em&gt;Custom Post&lt;/em&gt; en el menú de administración de WordPress.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;supports&lt;/strong&gt;: Un array con los distintos campos que queremos que este &lt;em&gt;Custom Post&lt;/em&gt; tenga en el panel de creación y edición, en este caso decimos que queremos que tenga título, imagen predeterminada y el campo de edición del post.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Añadimos el código anterior a nuestro fichero &lt;em&gt;functions.php&lt;/em&gt; y al guardar y refrescar tendremos disponible nuestro &lt;em&gt;Custom Post&lt;/em&gt;. Recomiendo, que para no tener dependencia entre el &lt;em&gt;Custom Post&lt;/em&gt; y el &lt;em&gt;Theme&lt;/em&gt;, separemos ambas cosas, creándolo como un plugin, en este caso, podemos crear un fichero en el directorio plugins al que llamaremos como queramos y cuyo contenido será algo así:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    &amp;lt;?php

    /*
    Plugin Name: Custom Post Trabajos
    Description: Custom posts de trabajos.
    Version: ...
    Author: ...
    Author Uri: ...
    License: ...
    */

    /* Aquí añadimos el código anterior que define el custom post */

    ...
&lt;/code&gt;&lt;/pre&gt;
</content:encoded></item></channel></rss>