Stack tecnológico de un programador web moderno en 2026
El programador web de 2026 debe dominar un ecosistema tecnológico mucho más amplio y sofisticado que hace una década. Ya no basta con HTML, CSS y jQuery.
En este artículo, exploraré el stack completo que un programador web profesional debe conocer, desde el frontend hasta DevOps e inteligencia artificial, explicando por qué cada tecnología es relevante y cómo se integran en proyectos reales.
Principios antes de herramientas
Antes de listar tecnologías, recordemos los principios que guían al programador web moderno:
1. Full-stack capability
El desarrollador moderno debe entender toda la stack:
- No necesitas ser experto en todo
- Pero sí competente en frontend, backend y deployment
- Permite tomar mejores decisiones arquitectónicas
- Facilita debugging de problemas end-to-end
2. TypeScript first
JavaScript dinámico está obsoleto:
- Tipos previenen bugs en desarrollo
- IDEs con autocompletado inteligente
- Refactoring seguro
- Documentación implícita
3. Testing obligatorio
El código sin tests es código legacy desde día 1:
- TDD (Test-Driven Development) no negociable
- Cobertura >80% mínima
- Tests unitarios, integración y E2E
- CI/CD ejecutando tests automáticamente
4. Developer Experience (DX)
Productividad depende de buenas herramientas:
- Hot reload para feedback inmediato
- Linting y formatting automático
- Type checking en tiempo real
- Debug tools sofisticados
Ahora sí, veamos el stack tecnológico actual.
Frontend: La cara visible de la aplicación
El frontend ha evolucionado de páginas estáticas a aplicaciones complejas.
React: El estándar de facto
Por qué React sigue dominando en 2026:
<span <span class="hljs-keyword">class</span>=<span class="hljs-string">"hljs-comment"</span>><span class="hljs-comment">// Component moderno con TypeScript y hooks</span></span>
<span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-keyword"</span>></span>import<span class="hljs-tag"></<span class="hljs-name">span</span>></span></span> { useState, useEffect } <span <span class="hljs-keyword">class</span>=<span class="hljs-string">"hljs-keyword"</span>><span class="hljs-keyword">from</span><<span class="hljs-regexp">/span> <span class="hljs-string">&#x27;react&#x27;</</span>span>
<span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-keyword"</span>></span>interface<span class="hljs-tag"></<span class="hljs-name">span</span>></span></span> <span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-title class_"</span>></span>User<span class="hljs-tag"></<span class="hljs-name">span</span>></span></span> {
<span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-attr"</span>></span>id<span class="hljs-tag"></<span class="hljs-name">span</span>></span></span>: <span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-built_in"</span>></span>number<span class="hljs-tag"></<span class="hljs-name">span</span>></span></span>
<span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-attr"</span>></span>name<span class="hljs-tag"></<span class="hljs-name">span</span>></span></span>: <span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-built_in"</span>></span>string<span class="hljs-tag"></<span class="hljs-name">span</span>></span></span>
<span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-attr"</span>></span>email<span class="hljs-tag"></<span class="hljs-name">span</span>></span></span>: <span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-built_in"</span>></span>string<span class="hljs-tag"></<span class="hljs-name">span</span>></span></span>
}
<span <span class="hljs-keyword">class</span>=<span class="hljs-string">"hljs-keyword"</span>><span class="hljs-keyword">function</span><<span class="hljs-regexp">/span> <span class="hljs-title function_">UserProfile</</span>span>(<span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-params"</span>></span>{ userId }: { userId: <span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-built_in"</span>></span>number<span class="hljs-tag"></<span class="hljs-name">span</span>></span> }<span class="hljs-tag"></<span class="hljs-name">span</span>></span></span>) {
<span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-keyword"</span>></span>const<span class="hljs-tag"></<span class="hljs-name">span</span>></span></span> [user, setUser] = useState&lt;<span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-title class_"</span>></span>User<span class="hljs-tag"></<span class="hljs-name">span</span>></span></span> | <span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-literal"</span>></span>null<span class="hljs-tag"></<span class="hljs-name">span</span>></span></span>&gt;(<span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-literal"</span>></span>null<span class="hljs-tag"></<span class="hljs-name">span</span>></span></span>)
<span <span class="hljs-keyword">class</span>=<span class="hljs-string">"hljs-keyword"</span>><span class="hljs-keyword">const</span><<span class="hljs-regexp">/span> [loading, setLoading] = <span class="hljs-title function_">useState</</span>span>(<span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-literal"</span>></span>true<span class="hljs-tag"></<span class="hljs-name">span</span>></span></span>)
<span <span class="hljs-keyword">class</span>=<span class="hljs-string">"hljs-title function_"</span>>useEffect<<span class="hljs-regexp">/span>(<span class="hljs-function">() =&gt;</</span>span> {
<span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-title function_"</span>></span>fetch<span class="hljs-tag"></<span class="hljs-name">span</span>></span></span>(<span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-string"</span>></span>`/api/users/<span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-subst"</span>></span>${userId}<span class="hljs-tag"></<span class="hljs-name">span</span>></span>`<span class="hljs-tag"></<span class="hljs-name">span</span>></span></span>)
.<span <span class="hljs-keyword">class</span>=<span class="hljs-string">"hljs-title function_"</span>>then<<span class="hljs-regexp">/span>(<span class="hljs-function"><span class="hljs-params">res</</span>span> =&gt;<<span class="hljs-regexp">/span> res.<span class="hljs-title function_">json</</span>span>())
.<span <span class="hljs-keyword">class</span>=<span class="hljs-string">"hljs-title function_"</span>>then<<span class="hljs-regexp">/span>(<span class="hljs-function"><span class="hljs-params">data</</span>span> =&gt;</span> {
<span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-title function_"</span>></span>setUser<span class="hljs-tag"></<span class="hljs-name">span</span>></span></span>(data)
<span <span class="hljs-keyword">class</span>=<span class="hljs-string">"hljs-title function_"</span>>setLoading<<span class="hljs-regexp">/span>(<span class="hljs-literal">false</</span>span>)
})
}, [userId])
<span <span class="hljs-keyword">class</span>=<span class="hljs-string">"hljs-keyword"</span>><span class="hljs-keyword">if</span><<span class="hljs-regexp">/span> (loading) <span class="hljs-keyword">return</</span>span> <span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"language-xml"</span>></span><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-tag"</span>></span><span class="hljs-symbol">&lt;</span><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-name"</span>></span>div<span class="hljs-tag"></<span class="hljs-name">span</span>></span><span class="hljs-symbol">&gt;</span><span class="hljs-tag"></<span class="hljs-name">span</span>></span>Cargando...<span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-tag"</span>></span><span class="hljs-symbol">&lt;</span>/<span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-name"</span>></span>div<span class="hljs-tag"></<span class="hljs-name">span</span>></span><span class="hljs-symbol">&gt;</span><span class="hljs-tag"></<span class="hljs-name">span</span>></span><span class="hljs-tag"></<span class="hljs-name">span</span>></span></span>
<span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-keyword"</span>></span>if<span class="hljs-tag"></<span class="hljs-name">span</span>></span></span> (!user) <span <span class="hljs-keyword">class</span>=<span class="hljs-string">"hljs-keyword"</span>><span class="hljs-keyword">return</span><<span class="hljs-regexp">/span> <span class="language-xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</</span>span>&gt;<<span class="hljs-regexp">/span>Usuario no encontrado<span class="hljs-tag">&lt;/</span><span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-name"</span>></span>div<span class="hljs-tag"></<span class="hljs-name">span</span>></span></span>&gt;<<span class="hljs-regexp">/span></</span>span>
<span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-keyword"</span>></span>return<span class="hljs-tag"></<span class="hljs-name">span</span>></span></span> (
<span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"language-xml"</span>></span><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-tag"</span>></span><span class="hljs-symbol">&lt;</span><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-name"</span>></span>div<span class="hljs-tag"></<span class="hljs-name">span</span>></span> <span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-attr"</span>></span>className<span class="hljs-tag"></<span class="hljs-name">span</span>></span>=<span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-string"</span>></span><span class="hljs-symbol">&quot;</span>user-profile<span class="hljs-symbol">&quot;</span><span class="hljs-tag"></<span class="hljs-name">span</span>></span><span class="hljs-symbol">&gt;</span><span class="hljs-tag"></<span class="hljs-name">span</span>></span>
<span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-tag"</span>></span><span class="hljs-symbol">&lt;</span><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-name"</span>></span>h1<span class="hljs-tag"></<span class="hljs-name">span</span>></span><span class="hljs-symbol">&gt;</span><span class="hljs-tag"></<span class="hljs-name">span</span>></span>{user.name}<span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-tag"</span>></span><span class="hljs-symbol">&lt;</span>/<span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-name"</span>></span>h1<span class="hljs-tag"></<span class="hljs-name">span</span>></span><span class="hljs-symbol">&gt;</span><span class="hljs-tag"></<span class="hljs-name">span</span>></span>
<span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-tag"</span>></span><span class="hljs-symbol">&lt;</span><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-name"</span>></span>p<span class="hljs-tag"></<span class="hljs-name">span</span>></span><span class="hljs-symbol">&gt;</span><span class="hljs-tag"></<span class="hljs-name">span</span>></span>{user.email}<span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-tag"</span>></span><span class="hljs-symbol">&lt;</span>/<span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-name"</span>></span>p<span class="hljs-tag"></<span class="hljs-name">span</span>></span><span class="hljs-symbol">&gt;</span><span class="hljs-tag"></<span class="hljs-name">span</span>></span>
<span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-tag"</span>></span><span class="hljs-symbol">&lt;</span>/<span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-name"</span>></span>div<span class="hljs-tag"></<span class="hljs-name">span</span>></span><span class="hljs-symbol">&gt;</span><span class="hljs-tag"></<span class="hljs-name">span</span>></span><span class="hljs-tag"></<span class="hljs-name">span</span>></span></span>
)
}
Ventajas:
- Ecosistema maduro y estable
- Componentes reutilizables
- Virtual DOM para rendimiento
- Hooks para lógica compartida
- Compatibilidad con Next.js
Next.js: React para producción
El framework que todo programador web debe dominar:
Next.js transforma React en una plataforma completa:
- SSR (Server-Side Rendering): SEO perfecto
- SSG (Static Site Generation): Rendimiento óptimo
- API Routes: Backend integrado
- Image Optimization: Imágenes automáticamente optimizadas
- File-based routing: Estructura clara
<span <span class="hljs-keyword">class</span>=<span class="hljs-string">"hljs-comment"</span>><span class="hljs-comment">// app/servicios/[slug]/page.tsx</span></span>
<span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-keyword"</span>></span>import<span class="hljs-tag"></<span class="hljs-name">span</span>></span></span> { <span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-title class_"</span>></span>Metadata<span class="hljs-tag"></<span class="hljs-name">span</span>></span></span> } <span <span class="hljs-keyword">class</span>=<span class="hljs-string">"hljs-keyword"</span>><span class="hljs-keyword">from</span><<span class="hljs-regexp">/span> <span class="hljs-string">&#x27;next&#x27;</</span>span>
<span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-keyword"</span>></span>export<span class="hljs-tag"></<span class="hljs-name">span</span>></span></span> <span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-keyword"</span>></span>async<span class="hljs-tag"></<span class="hljs-name">span</span>></span></span> <span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-keyword"</span>></span>function<span class="hljs-tag"></<span class="hljs-name">span</span>></span></span> <span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-title function_"</span>></span>generateMetadata<span class="hljs-tag"></<span class="hljs-name">span</span>></span></span>(<span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-params"</span>></span>{
params
}: {
params: { slug: <span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-built_in"</span>></span>string<span class="hljs-tag"></<span class="hljs-name">span</span>></span> }
}<span class="hljs-tag"></<span class="hljs-name">span</span>></span></span>): <span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-title class_"</span>></span>Promise<span class="hljs-tag"></<span class="hljs-name">span</span>></span></span>&lt;<span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-title class_"</span>></span>Metadata<span class="hljs-tag"></<span class="hljs-name">span</span>></span></span>&gt; {
<span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-keyword"</span>></span>return<span class="hljs-tag"></<span class="hljs-name">span</span>></span></span> {
<span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-attr"</span>></span>title<span class="hljs-tag"></<span class="hljs-name">span</span>></span></span>: <span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-string"</span>></span>`Servicio de <span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-subst"</span>></span>${params.slug}<span class="hljs-tag"></<span class="hljs-name">span</span>></span>`<span class="hljs-tag"></<span class="hljs-name">span</span>></span></span>,
<span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-attr"</span>></span>description<span class="hljs-tag"></<span class="hljs-name">span</span>></span></span>: <span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-string"</span>></span><span class="hljs-symbol">&#x27;</span>Descripción optimizada para SEO<span class="hljs-symbol">&#x27;</span><span class="hljs-tag"></<span class="hljs-name">span</span>></span></span>
}
}
<span <span class="hljs-keyword">class</span>=<span class="hljs-string">"hljs-keyword"</span>><span class="hljs-keyword">export</span><<span class="hljs-regexp">/span> <span class="hljs-keyword">default</</span>span> <span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-keyword"</span>></span>function<span class="hljs-tag"></<span class="hljs-name">span</span>></span></span> <span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-title function_"</span>></span>ServicioPage<span class="hljs-tag"></<span class="hljs-name">span</span>></span></span>(<span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-params"</span>></span>{
params
}: {
params: { slug: <span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-built_in"</span>></span>string<span class="hljs-tag"></<span class="hljs-name">span</span>></span> }
}<span class="hljs-tag"></<span class="hljs-name">span</span>></span></span>) {
<span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-keyword"</span>></span>return<span class="hljs-tag"></<span class="hljs-name">span</span>></span></span> <span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"language-xml"</span>></span><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-tag"</span>></span><span class="hljs-symbol">&lt;</span><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-name"</span>></span>div<span class="hljs-tag"></<span class="hljs-name">span</span>></span><span class="hljs-symbol">&gt;</span><span class="hljs-tag"></<span class="hljs-name">span</span>></span>Contenido del servicio {params.slug}<span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-tag"</span>></span><span class="hljs-symbol">&lt;</span>/<span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-name"</span>></span>div<span class="hljs-tag"></<span class="hljs-name">span</span>></span><span class="hljs-symbol">&gt;</span><span class="hljs-tag"></<span class="hljs-name">span</span>></span><span class="hljs-tag"></<span class="hljs-name">span</span>></span></span>
}
Uso Next.js en prácticamente todos mis proyectos web profesionales por su balance perfecto entre DX y rendimiento.
TypeScript: Seguridad de tipos obligatoria
Por qué TypeScript es no negociable en 2026:
<span <span class="hljs-keyword">class</span>=<span class="hljs-string">"hljs-comment"</span>><span class="hljs-comment">// Sin TypeScript: bugs en runtime</span></span>
<span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-keyword"</span>></span>function<span class="hljs-tag"></<span class="hljs-name">span</span>></span></span> <span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-title function_"</span>></span>calculatePrice<span class="hljs-tag"></<span class="hljs-name">span</span>></span></span>(<span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-params"</span>></span>quantity, price<span class="hljs-tag"></<span class="hljs-name">span</span>></span></span>) {
<span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-keyword"</span>></span>return<span class="hljs-tag"></<span class="hljs-name">span</span>></span></span> quantity * price <span <span class="hljs-keyword">class</span>=<span class="hljs-string">"hljs-comment"</span>><span class="hljs-comment">// ¿Qué pasa si alguien pasa strings?</span></span>
}
<span <span class="hljs-keyword">class</span>=<span class="hljs-string">"hljs-comment"</span>><span class="hljs-comment">// Con TypeScript: bugs en desarrollo</span></span>
<span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-keyword"</span>></span>function<span class="hljs-tag"></<span class="hljs-name">span</span>></span></span> <span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-title function_"</span>></span>calculatePrice<span class="hljs-tag"></<span class="hljs-name">span</span>></span></span>(<span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-params"</span>></span>
<span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-attr"</span>></span>quantity<span class="hljs-tag"></<span class="hljs-name">span</span>></span>: <span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-built_in"</span>></span>number<span class="hljs-tag"></<span class="hljs-name">span</span>></span>,
<span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-attr"</span>></span>price<span class="hljs-tag"></<span class="hljs-name">span</span>></span>: <span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-built_in"</span>></span>number<span class="hljs-tag"></<span class="hljs-name">span</span>></span>
<span class="hljs-tag"></<span class="hljs-name">span</span>></span></span>): <span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-built_in"</span>></span>number<span class="hljs-tag"></<span class="hljs-name">span</span>></span></span> {
<span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-keyword"</span>></span>return<span class="hljs-tag"></<span class="hljs-name">span</span>></span></span> quantity * price <span <span class="hljs-keyword">class</span>=<span class="hljs-string">"hljs-comment"</span>><span class="hljs-comment">// Error si recibes tipos incorrectos</span></span>
}
<span <span class="hljs-keyword">class</span>=<span class="hljs-string">"hljs-comment"</span>><span class="hljs-comment">// Tipos complejos para seguridad</span></span>
<span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-keyword"</span>></span>interface<span class="hljs-tag"></<span class="hljs-name">span</span>></span></span> <span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-title class_"</span>></span>Product<span class="hljs-tag"></<span class="hljs-name">span</span>></span></span> {
<span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-attr"</span>></span>id<span class="hljs-tag"></<span class="hljs-name">span</span>></span></span>: <span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-built_in"</span>></span>string<span class="hljs-tag"></<span class="hljs-name">span</span>></span></span>
<span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-attr"</span>></span>name<span class="hljs-tag"></<span class="hljs-name">span</span>></span></span>: <span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-built_in"</span>></span>string<span class="hljs-tag"></<span class="hljs-name">span</span>></span></span>
<span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-attr"</span>></span>price<span class="hljs-tag"></<span class="hljs-name">span</span>></span></span>: <span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-built_in"</span>></span>number<span class="hljs-tag"></<span class="hljs-name">span</span>></span></span>
<span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-attr"</span>></span>stock<span class="hljs-tag"></<span class="hljs-name">span</span>></span></span>: <span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-built_in"</span>></span>number<span class="hljs-tag"></<span class="hljs-name">span</span>></span></span>
<span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-attr"</span>></span>category<span class="hljs-tag"></<span class="hljs-name">span</span>></span></span>: <span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-string"</span>></span><span class="hljs-symbol">&#x27;</span>web<span class="hljs-symbol">&#x27;</span><span class="hljs-tag"></<span class="hljs-name">span</span>></span></span> | <span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-string"</span>></span><span class="hljs-symbol">&#x27;</span>ia<span class="hljs-symbol">&#x27;</span><span class="hljs-tag"></<span class="hljs-name">span</span>></span></span> | <span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-string"</span>></span><span class="hljs-symbol">&#x27;</span>consultoria<span class="hljs-symbol">&#x27;</span><span class="hljs-tag"></<span class="hljs-name">span</span>></span></span>
}
<span <span class="hljs-keyword">class</span>=<span class="hljs-string">"hljs-keyword"</span>><span class="hljs-keyword">function</span><<span class="hljs-regexp">/span> <span class="hljs-title function_">processProduct</</span>span>(<span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-params"</span>></span><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-attr"</span>></span>product<span class="hljs-tag"></<span class="hljs-name">span</span>></span>: <span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-title class_"</span>></span>Product<span class="hljs-tag"></<span class="hljs-name">span</span>></span><span class="hljs-tag"></<span class="hljs-name">span</span>></span></span>): <span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-built_in"</span>></span>void<span class="hljs-tag"></<span class="hljs-name">span</span>></span></span> {
<span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-comment"</span>></span>// IDE autocompleta propiedades<span class="hljs-tag"></<span class="hljs-name">span</span>></span></span>
<span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-comment"</span>></span>// Refactoring seguro<span class="hljs-tag"></<span class="hljs-name">span</span>></span></span>
<span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-comment"</span>></span>// Documentación implícita<span class="hljs-tag"></<span class="hljs-name">span</span>></span></span>
}
Beneficios reales:
- 40-80% menos bugs en producción
- Refactoring sin miedo
- Documentación que nunca se desactualiza
- Onboarding de nuevos developers más rápido
Tailwind CSS: Utility-first styling
Por qué Tailwind ha ganado la guerra de CSS:
<span <span class="hljs-keyword">class</span>=<span class="hljs-string">"hljs-comment"</span>><span class="hljs-comment">// Antes: CSS separado, naming decisions, especificidad</span></span>
&lt;div className=<span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-string"</span>></span><span class="hljs-symbol">&quot;</span>user-card<span class="hljs-symbol">&quot;</span><span class="hljs-tag"></<span class="hljs-name">span</span>></span></span>&gt;
<span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"language-xml"</span>></span><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-tag"</span>></span><span class="hljs-symbol">&lt;</span><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-name"</span>></span>h2<span class="hljs-tag"></<span class="hljs-name">span</span>></span> <span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-attr"</span>></span>className<span class="hljs-tag"></<span class="hljs-name">span</span>></span>=<span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-string"</span>></span><span class="hljs-symbol">&quot;</span>user-card__title<span class="hljs-symbol">&quot;</span><span class="hljs-tag"></<span class="hljs-name">span</span>></span><span class="hljs-symbol">&gt;</span><span class="hljs-tag"></<span class="hljs-name">span</span>></span>Título<span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-tag"</span>></span><span class="hljs-symbol">&lt;</span>/<span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-name"</span>></span>h2<span class="hljs-tag"></<span class="hljs-name">span</span>></span><span class="hljs-symbol">&gt;</span><span class="hljs-tag"></<span class="hljs-name">span</span>></span><span class="hljs-tag"></<span class="hljs-name">span</span>></span></span>
&lt;/div&gt;
<span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-comment"</span>></span>// Ahora: Tailwind utilities, composición rápida<span class="hljs-tag"></<span class="hljs-name">span</span>></span></span>
<span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"language-xml"</span>></span><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-tag"</span>></span><span class="hljs-symbol">&lt;</span><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-name"</span>></span>div<span class="hljs-tag"></<span class="hljs-name">span</span>></span> <span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-attr"</span>></span>className<span class="hljs-tag"></<span class="hljs-name">span</span>></span>=<span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-string"</span>></span><span class="hljs-symbol">&quot;</span>bg-white rounded-lg shadow-md p-6<span class="hljs-symbol">&quot;</span><span class="hljs-tag"></<span class="hljs-name">span</span>></span><span class="hljs-symbol">&gt;</span><span class="hljs-tag"></<span class="hljs-name">span</span>></span>
<span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-tag"</span>></span><span class="hljs-symbol">&lt;</span><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-name"</span>></span>h2<span class="hljs-tag"></<span class="hljs-name">span</span>></span> <span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-attr"</span>></span>className<span class="hljs-tag"></<span class="hljs-name">span</span>></span>=<span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-string"</span>></span><span class="hljs-symbol">&quot;</span>text-2xl font-bold text-gray-800<span class="hljs-symbol">&quot;</span><span class="hljs-tag"></<span class="hljs-name">span</span>></span><span class="hljs-symbol">&gt;</span><span class="hljs-tag"></<span class="hljs-name">span</span>></span>Título<span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-tag"</span>></span><span class="hljs-symbol">&lt;</span>/<span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-name"</span>></span>h2<span class="hljs-tag"></<span class="hljs-name">span</span>></span><span class="hljs-symbol">&gt;</span><span class="hljs-tag"></<span class="hljs-name">span</span>></span>
<span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-tag"</span>></span><span class="hljs-symbol">&lt;</span>/<span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-name"</span>></span>div<span class="hljs-tag"></<span class="hljs-name">span</span>></span><span class="hljs-symbol">&gt;</span><span class="hljs-tag"></<span class="hljs-name">span</span>></span><span class="hljs-tag"></<span class="hljs-name">span</span>></span></span>
Ventajas:
- Desarrollo ultra-rápido sin cambiar contexto
- Diseño consistente automáticamente
- CSS producido muy optimizado (solo clases usadas)
- Responsive design simplificado
- Dark mode trivial
Alternativas viable: Vue y Svelte
Vue.js sigue siendo excelente para:
- Proyectos más pequeños
- Teams que prefieren sintaxis templates
- Curva de aprendizaje más suave
Svelte está creciendo para:
- Rendimiento extremo (no virtual DOM)
- Bundle sizes mínimos
- DX excepcional
Personalmente, me especializo en React/Next.js porque cubre el 90% de casos de uso con calidad enterprise.
Backend: El cerebro de la aplicación
El backend maneja lógica de negocio, datos y seguridad.
Node.js con Express o Fastify
JavaScript/TypeScript en el backend:
<span <span class="hljs-keyword">class</span>=<span class="hljs-string">"hljs-comment"</span>><span class="hljs-comment">// Express con TypeScript</span></span>
<span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-keyword"</span>></span>import<span class="hljs-tag"></<span class="hljs-name">span</span>></span></span> express, { <span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-title class_"</span>></span>Request<span class="hljs-tag"></<span class="hljs-name">span</span>></span></span>, <span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-title class_"</span>></span>Response<span class="hljs-tag"></<span class="hljs-name">span</span>></span></span> } <span <span class="hljs-keyword">class</span>=<span class="hljs-string">"hljs-keyword"</span>><span class="hljs-keyword">from</span><<span class="hljs-regexp">/span> <span class="hljs-string">&#x27;express&#x27;</</span>span>
<span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-keyword"</span>></span>const<span class="hljs-tag"></<span class="hljs-name">span</span>></span></span> app = <span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-title function_"</span>></span>express<span class="hljs-tag"></<span class="hljs-name">span</span>></span></span>()
app.<span <span class="hljs-keyword">class</span>=<span class="hljs-string">"hljs-title function_"</span>>get<<span class="hljs-regexp">/span>(<span class="hljs-string">&#x27;/</span>api/users/:id&#x27;<<span class="hljs-regexp">/span>, <span class="hljs-title function_">async</</span>span> (<span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-attr"</span>></span>req<span class="hljs-tag"></<span class="hljs-name">span</span>></span></span>: <span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-title class_"</span>></span>Request<span class="hljs-tag"></<span class="hljs-name">span</span>></span></span>, <span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-attr"</span>></span>res<span class="hljs-tag"></<span class="hljs-name">span</span>></span></span>: <span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-title class_"</span>></span>Response<span class="hljs-tag"></<span class="hljs-name">span</span>></span></span>) =&gt; {
<span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-keyword"</span>></span>const<span class="hljs-tag"></<span class="hljs-name">span</span>></span></span> userId = <span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-built_in"</span>></span>parseInt<span class="hljs-tag"></<span class="hljs-name">span</span>></span></span>(req.<span <span class="hljs-keyword">class</span>=<span class="hljs-string">"hljs-property"</span>>params<<span class="hljs-regexp">/span>.<span class="hljs-property">id</</span>span>)
<span <span class="hljs-keyword">class</span>=<span class="hljs-string">"hljs-keyword"</span>><span class="hljs-keyword">const</span><<span class="hljs-regexp">/span> user = <span class="hljs-keyword">await</</span>span> db.<span <span class="hljs-keyword">class</span>=<span class="hljs-string">"hljs-property"</span>>users<<span class="hljs-regexp">/span>.<span class="hljs-title function_">findById</</span>span>(userId)
<span <span class="hljs-keyword">class</span>=<span class="hljs-string">"hljs-keyword"</span>><span class="hljs-keyword">if</span></span> (!user) {
<span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-keyword"</span>></span>return<span class="hljs-tag"></<span class="hljs-name">span</span>></span></span> res.<span <span class="hljs-keyword">class</span>=<span class="hljs-string">"hljs-title function_"</span>>status<<span class="hljs-regexp">/span>(<span class="hljs-number">404</</span>span>).<span <span class="hljs-keyword">class</span>=<span class="hljs-string">"hljs-title function_"</span>>json<<span class="hljs-regexp">/span>({ <span class="hljs-attr">error</</span>span>: <span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-string"</span>></span><span class="hljs-symbol">&#x27;</span>User not found<span class="hljs-symbol">&#x27;</span><span class="hljs-tag"></<span class="hljs-name">span</span>></span></span> })
}
res.<span <span class="hljs-keyword">class</span>=<span class="hljs-string">"hljs-title function_"</span>>json</span>(user)
})
app.<span <span class="hljs-keyword">class</span>=<span class="hljs-string">"hljs-title function_"</span>>listen<<span class="hljs-regexp">/span>(<span class="hljs-number">3000</</span>span>)
Cuándo usar Node.js:
- Aplicaciones real-time (WebSockets)
- APIs REST rápidas
- Microservicios ligeros
- Cuando frontend es React/Next.js (mismo lenguaje)
Python con Django o FastAPI
Python para proyectos complejos:
<span <span class="hljs-keyword">class</span>=<span class="hljs-string">"hljs-comment"</span>><span class="hljs-comment"># FastAPI con type hints</span></span>
<span <span class="hljs-keyword">class</span>=<span class="hljs-string">"hljs-keyword"</span>><span class="hljs-keyword">from</span></span> fastapi <span <span class="hljs-keyword">class</span>=<span class="hljs-string">"hljs-keyword"</span>><span class="hljs-keyword">import</span></span> FastAPI, HTTPException
<span <span class="hljs-keyword">class</span>=<span class="hljs-string">"hljs-keyword"</span>><span class="hljs-keyword">from</span></span> pydantic <span <span class="hljs-keyword">class</span>=<span class="hljs-string">"hljs-keyword"</span>><span class="hljs-keyword">import</span></span> BaseModel
app = FastAPI()
<span <span class="hljs-keyword">class</span>=<span class="hljs-string">"hljs-keyword"</span>><span class="hljs-keyword">class</span></span> <span <span class="hljs-keyword">class</span>=<span class="hljs-string">"hljs-title class_"</span>>User</span>(<span <span class="hljs-keyword">class</span>=<span class="hljs-string">"hljs-title class_ inherited__"</span>>BaseModel</span>):
<span <span class="hljs-keyword">class</span>=<span class="hljs-string">"hljs-built_in"</span>><span class="hljs-built_in">id</span></span>: <span <span class="hljs-keyword">class</span>=<span class="hljs-string">"hljs-built_in"</span>><span class="hljs-built_in">int</span></span>
name: <span <span class="hljs-keyword">class</span>=<span class="hljs-string">"hljs-built_in"</span>><span class="hljs-built_in">str</span></span>
email: <span <span class="hljs-keyword">class</span>=<span class="hljs-string">"hljs-built_in"</span>><span class="hljs-built_in">str</span></span>
<span <span class="hljs-keyword">class</span>=<span class="hljs-string">"hljs-meta"</span>>@app.get(<span <span class="hljs-keyword">class</span>=<span class="hljs-string">"hljs-params"</span>><span <span class="hljs-keyword">class</span>=<span class="hljs-string">"hljs-string"</span>>&quot;/users/{user_id}&quot;</span>, response_model=User</span>)</span>
<span <span class="hljs-keyword">class</span>=<span class="hljs-string">"hljs-keyword"</span>><span class="hljs-keyword">async</span></span> <span <span class="hljs-keyword">class</span>=<span class="hljs-string">"hljs-keyword"</span>><span class="hljs-keyword">def</span></span> <span <span class="hljs-keyword">class</span>=<span class="hljs-string">"hljs-title function_"</span>>get_user</span>(<span <span class="hljs-keyword">class</span>=<span class="hljs-string">"hljs-params"</span>>user_id: <span <span class="hljs-keyword">class</span>=<span class="hljs-string">"hljs-built_in"</span>><span class="hljs-built_in">int</span></span></span>):
user = <span <span class="hljs-keyword">class</span>=<span class="hljs-string">"hljs-keyword"</span>><span class="hljs-keyword">await</span></span> db.get_user(user_id)
<span <span class="hljs-keyword">class</span>=<span class="hljs-string">"hljs-keyword"</span>><span class="hljs-keyword">if</span></span> <span <span class="hljs-keyword">class</span>=<span class="hljs-string">"hljs-keyword"</span>><span class="hljs-keyword">not</span></span> user:
<span <span class="hljs-keyword">class</span>=<span class="hljs-string">"hljs-keyword"</span>><span class="hljs-keyword">raise</span></span> HTTPException(status_code=<span <span class="hljs-keyword">class</span>=<span class="hljs-string">"hljs-number"</span>><span class="hljs-number">404</span></span>, detail=<span <span class="hljs-keyword">class</span>=<span class="hljs-string">"hljs-string"</span>>&quot;User <span class="hljs-keyword">not</span> found&quot;</span>)
<span <span class="hljs-keyword">class</span>=<span class="hljs-string">"hljs-keyword"</span>><span class="hljs-keyword">return</span></span> user
Cuándo usar Python:
- Integración con IA y ML
- Sistemas RAG con LangChain
- Procesamiento de datos complejo
- Computer Vision con OpenCV
- NLP avanzado
Python es mi elección cuando el proyecto involucra ingeniería de IA.
PHP moderno con Symfony
PHP ha renacido con versión 8.x:
<span <span class="hljs-class"><span class="hljs-keyword">class</span>="<span class="hljs-title">hljs</span>-<span class="hljs-title">comment</span>">// <span class="hljs-title">PHP</span> 8.3 <span class="hljs-title">con</span> <span class="hljs-title">tipos</span> <span class="hljs-title">y</span> <span class="hljs-title">attributes</span></<span class="hljs-title">span</span>>
<<span class="hljs-title">span</span> <span class="hljs-title">class</span>="<span class="hljs-title">hljs</span>-<span class="hljs-title">meta</span>">#[<span class="hljs-title">Route</span></<span class="hljs-title">span</span>>(<<span class="hljs-title">span</span> <span class="hljs-title">class</span>="<span class="hljs-title">hljs</span>-<span class="hljs-title">string</span>">&#<span class="hljs-title">x27</span>;/<span class="hljs-title">api</span>/<span class="hljs-title">users</span>/</span>{id}&<span class="hljs-comment">#x27;</span>, <span class="hljs-attr">methods</span>: [<span class="hljs-string">&#x27;GET&#x27;</span>])<span class="hljs-meta">]</span></span>
<span <span class="hljs-class"><span class="hljs-keyword">class</span>="<span class="hljs-title">hljs</span>-<span class="hljs-title">keyword</span>"><span class="hljs-title">public</span></<span class="hljs-title">span</span>> <<span class="hljs-title">span</span> <span class="hljs-title">class</span>="<span class="hljs-title">hljs</span>-<span class="hljs-title">function</span>"><<span class="hljs-title">span</span> <span class="hljs-title">class</span>="<span class="hljs-title">hljs</span>-<span class="hljs-title">keyword</span>"><span class="hljs-title">function</span></<span class="hljs-title">span</span>> <<span class="hljs-title">span</span> <span class="hljs-title">class</span>="<span class="hljs-title">hljs</span>-<span class="hljs-title">title</span>"><span class="hljs-title">getUser</span></<span class="hljs-title">span</span>>(<<span class="hljs-title">span</span> <span class="hljs-title">class</span>="<span class="hljs-title">hljs</span>-<span class="hljs-title">params</span>"><<span class="hljs-title">span</span> <span class="hljs-title">class</span>="<span class="hljs-title">hljs</span>-<span class="hljs-title">keyword</span>"><span class="hljs-title">int</span></<span class="hljs-title">span</span>> <<span class="hljs-title">span</span> <span class="hljs-title">class</span>="<span class="hljs-title">hljs</span>-<span class="hljs-title">variable</span>">$<span class="hljs-title">id</span></<span class="hljs-title">span</span>></<span class="hljs-title">span</span>>): <<span class="hljs-title">span</span> <span class="hljs-title">class</span>="<span class="hljs-title">hljs</span>-<span class="hljs-title">title</span>"><span class="hljs-title">JsonResponse</span></<span class="hljs-title">span</span>>
</<span class="hljs-title">span</span>></span>{
<span <span class="hljs-class"><span class="hljs-keyword">class</span>="<span class="hljs-title">hljs</span>-<span class="hljs-title">variable</span>">$<span class="hljs-title">user</span></<span class="hljs-title">span</span>> = <<span class="hljs-title">span</span> <span class="hljs-title">class</span>="<span class="hljs-title">hljs</span>-<span class="hljs-title">variable</span> <span class="hljs-title">language_</span>">$<span class="hljs-title">this</span></<span class="hljs-title">span</span>>-&<span class="hljs-title">gt</span>;<span class="hljs-title">userRepository</span>-&<span class="hljs-title">gt</span>;<<span class="hljs-title">span</span> <span class="hljs-title">class</span>="<span class="hljs-title">hljs</span>-<span class="hljs-title">title</span> <span class="hljs-title">function_</span> <span class="hljs-title">invoke__</span>"><span class="hljs-title">find</span></<span class="hljs-title">span</span>>(<<span class="hljs-title">span</span> <span class="hljs-title">class</span>="<span class="hljs-title">hljs</span>-<span class="hljs-title">variable</span>">$<span class="hljs-title">id</span></<span class="hljs-title">span</span>>);
<<span class="hljs-title">span</span> <span class="hljs-title">class</span>="<span class="hljs-title">hljs</span>-<span class="hljs-title">keyword</span>"><span class="hljs-title">if</span></<span class="hljs-title">span</span>> (!<<span class="hljs-title">span</span> <span class="hljs-title">class</span>="<span class="hljs-title">hljs</span>-<span class="hljs-title">variable</span>">$<span class="hljs-title">user</span></<span class="hljs-title">span</span>>) </span>{
<span <span class="hljs-class"><span class="hljs-keyword">class</span>="<span class="hljs-title">hljs</span>-<span class="hljs-title">keyword</span>"><span class="hljs-title">return</span></<span class="hljs-title">span</span>> <<span class="hljs-title">span</span> <span class="hljs-title">class</span>="<span class="hljs-title">hljs</span>-<span class="hljs-title">keyword</span>"><span class="hljs-title">new</span></<span class="hljs-title">span</span>> <<span class="hljs-title">span</span> <span class="hljs-title">class</span>="<span class="hljs-title">hljs</span>-<span class="hljs-title">title</span> <span class="hljs-title">class_</span>"><span class="hljs-title">JsonResponse</span></<span class="hljs-title">span</span>>(
[<<span class="hljs-title">span</span> <span class="hljs-title">class</span>="<span class="hljs-title">hljs</span>-<span class="hljs-title">string</span>">&#<span class="hljs-title">x27</span>;<span class="hljs-title">error</span>&#<span class="hljs-title">x27</span>;</<span class="hljs-title">span</span>> =&<span class="hljs-title">gt</span>; <<span class="hljs-title">span</span> <span class="hljs-title">class</span>="<span class="hljs-title">hljs</span>-<span class="hljs-title">string</span>">&#<span class="hljs-title">x27</span>;<span class="hljs-title">User</span> <span class="hljs-title">not</span> <span class="hljs-title">found</span>&#<span class="hljs-title">x27</span>;</<span class="hljs-title">span</span>>],
404
);
}
<<span class="hljs-title">span</span> <span class="hljs-title">class</span>="<span class="hljs-title">hljs</span>-<span class="hljs-title">keyword</span>"><span class="hljs-title">return</span></<span class="hljs-title">span</span>> <<span class="hljs-title">span</span> <span class="hljs-title">class</span>="<span class="hljs-title">hljs</span>-<span class="hljs-title">keyword</span>"><span class="hljs-title">new</span></<span class="hljs-title">span</span>> <<span class="hljs-title">span</span> <span class="hljs-title">class</span>="<span class="hljs-title">hljs</span>-<span class="hljs-title">title</span> <span class="hljs-title">class_</span>"><span class="hljs-title">JsonResponse</span></<span class="hljs-title">span</span>>(<<span class="hljs-title">span</span> <span class="hljs-title">class</span>="<span class="hljs-title">hljs</span>-<span class="hljs-title">variable</span>">$<span class="hljs-title">user</span></<span class="hljs-title">span</span>>);
}</span>
Cuándo usar PHP:
- Clientes con hosting compartido
- Legacy systems que mantener
- Ecosistema maduro (Symfony, Laravel)
- Presupuestos ajustados (hosting más barato)
APIs: REST vs GraphQL
REST sigue siendo el estándar:
- Más simple de entender
- Caching HTTP standard
- Herramientas establecidas
GraphQL para casos específicos:
- Frontend necesita datos muy personalizados
- Reducir overfetching
- APIs públicas complejas
En mis proyectos de ecommerce y SaaS, uso REST con OpenAPI spec para documentación automática.
Bases de datos: Persistencia y cache
Elegir la base de datos correcta es crítico.
PostgreSQL: El rey de bases relacionales
Por qué PostgreSQL es mi default:
<span class="hljs-operator"><</span>span class<span class="hljs-operator">=</span>"hljs-comment"<span class="hljs-operator">></span><span class="hljs-comment">-- Tipos avanzados, JSON, full-text search</span></span>
<span class="hljs-operator"><</span>span class<span class="hljs-operator">=</span>"hljs-keyword"<span class="hljs-operator">></span><span class="hljs-keyword">CREATE TABLE</span><span class="hljs-operator"><</span><span class="hljs-operator">/</span>span<span class="hljs-operator">></span> products (
id SERIAL <span class="hljs-operator"><</span>span class<span class="hljs-operator">=</span>"hljs-keyword"<span class="hljs-operator">></span><span class="hljs-keyword">PRIMARY KEY</span><span class="hljs-operator"><</span><span class="hljs-operator">/</span>span<span class="hljs-operator">></span>,
name <span class="hljs-operator"><</span>span class<span class="hljs-operator">=</span>"hljs-type"<span class="hljs-operator">></span><span class="hljs-type">VARCHAR</span><span class="hljs-operator"><</span><span class="hljs-operator">/</span>span<span class="hljs-operator">></span>(<span class="hljs-operator"><</span>span class<span class="hljs-operator">=</span>"hljs-number"<span class="hljs-operator">></span><span class="hljs-number">255</span><span class="hljs-operator"><</span><span class="hljs-operator">/</span>span<span class="hljs-operator">></span>) <span class="hljs-operator"><</span>span class<span class="hljs-operator">=</span>"hljs-keyword"<span class="hljs-operator">></span><span class="hljs-keyword">NOT NULL</span><span class="hljs-operator"><</span><span class="hljs-operator">/</span>span<span class="hljs-operator">></span>,
description TEXT,
price <span class="hljs-operator"><</span>span class<span class="hljs-operator">=</span>"hljs-type"<span class="hljs-operator">></span><span class="hljs-type">DECIMAL</span><span class="hljs-operator"><</span><span class="hljs-operator">/</span>span<span class="hljs-operator">></span>(<span class="hljs-operator"><</span>span class<span class="hljs-operator">=</span>"hljs-number"<span class="hljs-operator">></span><span class="hljs-number">10</span><span class="hljs-operator"><</span><span class="hljs-operator">/</span>span<span class="hljs-operator">></span>, <span class="hljs-operator"><</span>span class<span class="hljs-operator">=</span>"hljs-number"<span class="hljs-operator">></span><span class="hljs-number">2</span><span class="hljs-operator"><</span><span class="hljs-operator">/</span>span<span class="hljs-operator">></span>) <span class="hljs-operator"><</span>span class<span class="hljs-operator">=</span>"hljs-keyword"<span class="hljs-operator">></span><span class="hljs-keyword">NOT NULL</span><span class="hljs-operator"><</span><span class="hljs-operator">/</span>span<span class="hljs-operator">></span>,
metadata JSONB, <span class="hljs-operator"><</span>span class<span class="hljs-operator">=</span>"hljs-comment"<span class="hljs-operator">></span><span class="hljs-comment">-- JSON con indexing</span></span>
search_vector tsvector, <span class="hljs-operator"><</span>span class<span class="hljs-operator">=</span>"hljs-comment"<span class="hljs-operator">></span><span class="hljs-comment">-- Full-text search</span></span>
created_at <span class="hljs-operator"><</span>span class<span class="hljs-operator">=</span>"hljs-type"<span class="hljs-operator">></span><span class="hljs-type">TIMESTAMP</span><span class="hljs-operator"><</span><span class="hljs-operator">/</span>span<span class="hljs-operator">></span> <span class="hljs-operator"><</span>span class<span class="hljs-operator">=</span>"hljs-keyword"<span class="hljs-operator">></span><span class="hljs-keyword">DEFAULT</span><span class="hljs-operator"><</span><span class="hljs-operator">/</span>span<span class="hljs-operator">></span> NOW()
);
<span class="hljs-operator"><</span>span class<span class="hljs-operator">=</span>"hljs-keyword"<span class="hljs-operator">></span><span class="hljs-keyword">CREATE</span><span class="hljs-operator"><</span><span class="hljs-operator">/</span>span<span class="hljs-operator">></span> INDEX idx_products_metadata
<span class="hljs-operator"><</span>span class<span class="hljs-operator">=</span>"hljs-keyword"<span class="hljs-operator">></span><span class="hljs-keyword">ON</span><span class="hljs-operator"><</span><span class="hljs-operator">/</span>span<span class="hljs-operator">></span> products <span class="hljs-operator"><</span>span class<span class="hljs-operator">=</span>"hljs-keyword"<span class="hljs-operator">></span><span class="hljs-keyword">USING</span><span class="hljs-operator"><</span><span class="hljs-operator">/</span>span<span class="hljs-operator">></span> GIN (metadata);
<span class="hljs-operator"><</span>span class<span class="hljs-operator">=</span>"hljs-keyword"<span class="hljs-operator">></span><span class="hljs-keyword">CREATE</span><span class="hljs-operator"><</span><span class="hljs-operator">/</span>span<span class="hljs-operator">></span> INDEX idx_products_search
<span class="hljs-operator"><</span>span class<span class="hljs-operator">=</span>"hljs-keyword"<span class="hljs-operator">></span><span class="hljs-keyword">ON</span><span class="hljs-operator"><</span><span class="hljs-operator">/</span>span<span class="hljs-operator">></span> products <span class="hljs-operator"><</span>span class<span class="hljs-operator">=</span>"hljs-keyword"<span class="hljs-operator">></span><span class="hljs-keyword">USING</span><span class="hljs-operator"><</span><span class="hljs-operator">/</span>span<span class="hljs-operator">></span> GIN (search_vector);
Ventajas:
- ACID compliant (transacciones confiables)
- Tipos de datos avanzados (JSON, arrays, UUID)
- Full-text search integrado
- Extensiones potentes (PostGIS para mapas)
- Performance excelente con tuning adecuado
MySQL/MariaDB: Compatibilidad universal
Cuándo sigue siendo buena opción:
- Hosting compartido (disponibilidad universal)
- Aplicaciones legacy
- Casos de uso simples
- Presupuesto muy ajustado
MongoDB: NoSQL para flexibilidad
Casos de uso específicos:
<span <span class="hljs-keyword">class</span>=<span class="hljs-string">"hljs-comment"</span>><span class="hljs-comment">// Schema flexible con Mongoose</span></span>
<span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-keyword"</span>></span>const<span class="hljs-tag"></<span class="hljs-name">span</span>></span></span> productSchema = <span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-keyword"</span>></span>new<span class="hljs-tag"></<span class="hljs-name">span</span>></span></span> <span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-title class_"</span>></span>Schema<span class="hljs-tag"></<span class="hljs-name">span</span>></span></span>({
<span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-attr"</span>></span>name<span class="hljs-tag"></<span class="hljs-name">span</span>></span></span>: <span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-title class_"</span>></span>String<span class="hljs-tag"></<span class="hljs-name">span</span>></span></span>,
<span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-attr"</span>></span>price<span class="hljs-tag"></<span class="hljs-name">span</span>></span></span>: <span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-title class_"</span>></span>Number<span class="hljs-tag"></<span class="hljs-name">span</span>></span></span>,
<span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-attr"</span>></span>attributes<span class="hljs-tag"></<span class="hljs-name">span</span>></span></span>: <span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-title class_"</span>></span>Schema<span class="hljs-tag"></<span class="hljs-name">span</span>></span></span>.<span <span class="hljs-keyword">class</span>=<span class="hljs-string">"hljs-property"</span>><span class="hljs-title class_">Types</span><<span class="hljs-regexp">/span>.<span class="hljs-property">Mixed</</span>span>, <span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-comment"</span>></span>// Cualquier estructura<span class="hljs-tag"></<span class="hljs-name">span</span>></span></span>
<span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-attr"</span>></span>tags<span class="hljs-tag"></<span class="hljs-name">span</span>></span></span>: [<span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-title class_"</span>></span>String<span class="hljs-tag"></<span class="hljs-name">span</span>></span></span>],
<span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-attr"</span>></span>reviews<span class="hljs-tag"></<span class="hljs-name">span</span>></span></span>: [{
<span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-attr"</span>></span>user<span class="hljs-tag"></<span class="hljs-name">span</span>></span></span>: <span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-title class_"</span>></span>String<span class="hljs-tag"></<span class="hljs-name">span</span>></span></span>,
<span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-attr"</span>></span>rating<span class="hljs-tag"></<span class="hljs-name">span</span>></span></span>: <span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-title class_"</span>></span>Number<span class="hljs-tag"></<span class="hljs-name">span</span>></span></span>,
<span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-attr"</span>></span>comment<span class="hljs-tag"></<span class="hljs-name">span</span>></span></span>: <span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-title class_"</span>></span>String<span class="hljs-tag"></<span class="hljs-name">span</span>></span></span>,
<span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-attr"</span>></span>date<span class="hljs-tag"></<span class="hljs-name">span</span>></span></span>: <span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-title class_"</span>></span>Date<span class="hljs-tag"></<span class="hljs-name">span</span>></span></span>
}]
})
Cuándo usar MongoDB:
- Schema altamente variable
- Rapid prototyping
- Logs y analytics
- Datos semi-estructurados
Redis: Cache y datos en memoria
Imprescindible para performance:
<span <span class="hljs-keyword">class</span>=<span class="hljs-string">"hljs-comment"</span>><span class="hljs-comment">// Cache de queries costosas</span></span>
<span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-keyword"</span>></span>async<span class="hljs-tag"></<span class="hljs-name">span</span>></span></span> <span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-keyword"</span>></span>function<span class="hljs-tag"></<span class="hljs-name">span</span>></span></span> <span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-title function_"</span>></span>getUser<span class="hljs-tag"></<span class="hljs-name">span</span>></span></span>(<span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-params"</span>></span><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-attr"</span>></span>userId<span class="hljs-tag"></<span class="hljs-name">span</span>></span>: <span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-built_in"</span>></span>number<span class="hljs-tag"></<span class="hljs-name">span</span>></span><span class="hljs-tag"></<span class="hljs-name">span</span>></span></span>): <span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-title class_"</span>></span>Promise<span class="hljs-tag"></<span class="hljs-name">span</span>></span></span>&lt;<span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-title class_"</span>></span>User<span class="hljs-tag"></<span class="hljs-name">span</span>></span></span>&gt; {
<span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-comment"</span>></span>// Intentar cache primero<span class="hljs-tag"></<span class="hljs-name">span</span>></span></span>
<span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-keyword"</span>></span>const<span class="hljs-tag"></<span class="hljs-name">span</span>></span></span> cached = <span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-keyword"</span>></span>await<span class="hljs-tag"></<span class="hljs-name">span</span>></span></span> redis.<span <span class="hljs-keyword">class</span>=<span class="hljs-string">"hljs-title function_"</span>>get<<span class="hljs-regexp">/span>(<span class="hljs-string">`user:<span class="hljs-subst">${userId}</</span>span><span class="hljs-string">`</span>)
<span class="hljs-keyword">if</span> (cached) <span class="hljs-keyword">return</span> <span class="hljs-title class_">JSON</span>.<span class="hljs-title function_">parse</span>(cached)
<span class="hljs-comment">// Si no está en cache, buscar en DB</span>
<span class="hljs-keyword">const</span> user = <span class="hljs-keyword">await</span> db.<span class="hljs-property">users</span>.<span class="hljs-title function_">findById</span>(userId)
<span class="hljs-comment">// Guardar en cache (TTL 1 hora)</span>
<span class="hljs-keyword">await</span> redis.<span class="hljs-title function_">setex</span>(
<span class="hljs-string">`</span><span class="hljs-attr">user</span>:<span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hljs-subst"</span>></span>${userId}<span class="hljs-tag"></<span class="hljs-name">span</span>></span></span><span class="hljs-string">`</span>,
<span class="hljs-number">3600</span>,
<span class="hljs-title class_">JSON</span>.<span class="hljs-title function_">stringify</span>(user)
)
<span class="hljs-keyword">return</span> user
}</span>
Casos de uso:
- Cache de queries frecuentes
- Sessions de usuario
- Rate limiting
- Pub/sub para real-time
- Queues de trabajos asíncronos
DevOps: De desarrollo a producción
Un programador web moderno debe saber deployar.
Docker: Entornos reproducibles
Containerización obligatoria:
<span class=<span class="hljs-string">"hljs-comment"</span>><span class="hljs-comment"># Dockerfile para Next.js app</span></span>
<span class=<span class="hljs-string">"hljs-keyword"</span>><span class="hljs-keyword">FROM</span></span> node:<span class=<span class="hljs-string">"hljs-number"</span>><span class="hljs-number">20</span></span>-alpine AS builder
<span class=<span class="hljs-string">"hljs-keyword"</span>><span class="hljs-keyword">WORKDIR</span><span class="language-bash"></span><span class=<span class="hljs-string">"language-bash"</span>> /app</span></span>
<span class=<span class="hljs-string">"hljs-keyword"</span>><span class="hljs-keyword">COPY</span><span class="language-bash"></span><span class=<span class="hljs-string">"language-bash"</span>> package*.json ./</span></span>
<span class=<span class="hljs-string">"hljs-keyword"</span>><span class="hljs-keyword">RUN</span><span class="language-bash"></span><span class=<span class="hljs-string">"language-bash"</span>> npm ci</span></span>
<span class=<span class="hljs-string">"hljs-keyword"</span>><span class="hljs-keyword">COPY</span><span class="language-bash"></span><span class=<span class="hljs-string">"language-bash"</span>> . .</span></span>
<span class=<span class="hljs-string">"hljs-keyword"</span>><span class="hljs-keyword">RUN</span><span class="language-bash"></span><span class=<span class="hljs-string">"language-bash"</span>> npm run build</span></span>
<span class=<span class="hljs-string">"hljs-keyword"</span>><span class="hljs-keyword">FROM</span></span> node:<span class=<span class="hljs-string">"hljs-number"</span>><span class="hljs-number">20</span></span>-alpine AS runner
<span class=<span class="hljs-string">"hljs-keyword"</span>><span class="hljs-keyword">WORKDIR</span><span class="language-bash"></span><span class=<span class="hljs-string">"language-bash"</span>> /app</span></span>
<span class=<span class="hljs-string">"hljs-keyword"</span>><span class="hljs-keyword">COPY</span><span class="language-bash"></span><span class=<span class="hljs-string">"language-bash"</span>> --from=builder /app/next.config.js ./</span></span>
<span class=<span class="hljs-string">"hljs-keyword"</span>><span class="hljs-keyword">COPY</span><span class="language-bash"></span><span class=<span class="hljs-string">"language-bash"</span>> --from=builder /app/public ./public</span></span>
<span class=<span class="hljs-string">"hljs-keyword"</span>><span class="hljs-keyword">COPY</span><span class="language-bash"></span><span class=<span class="hljs-string">"language-bash"</span>> --from=builder /app/.next ./.next</span></span>
<span class=<span class="hljs-string">"hljs-keyword"</span>><span class="hljs-keyword">COPY</span><span class="language-bash"></span><span class=<span class="hljs-string">"language-bash"</span>> --from=builder /app/node_modules ./node_modules</span></span>
<span class=<span class="hljs-string">"hljs-keyword"</span>><span class="hljs-keyword">EXPOSE</span></span> <span class=<span class="hljs-string">"hljs-number"</span>><span class="hljs-number">3000</span></span>
<span class=<span class="hljs-string">"hljs-keyword"</span>><span class="hljs-keyword">CMD</span><span class="language-bash"></span><span class=<span class="hljs-string">"language-bash"</span>> [<span class=<span class="hljs-string">"hljs-string"</span>>&quot;npm&quot;</span>, <span class=<span class="hljs-string">"hljs-string"</span>>&quot;start&quot;</span>]</span></span>
Beneficios:
- Entorno idéntico en dev, staging y prod
- Despliegue consistente
- Isolación de dependencias
- Facilita CI/CD
CI/CD: Automatización de calidad
GitHub Actions ejemplo:
<span class="hljs-string"><span</span> <span class="hljs-string">class="hljs-comment">#</span> <span class="hljs-string">.github/workflows/test-and-deploy.yml</span></span>
<span class="hljs-string"><span</span> <span class="hljs-string">class="hljs-attr">name:</span></span> <span class="hljs-string"><span</span> <span class="hljs-string">class="hljs-string">Test</span></span> <span class="hljs-string"><span</span> <span class="hljs-string">class="hljs-string">and</span></span> <span class="hljs-string"><span</span> <span class="hljs-string">class="hljs-string">Deploy</span></span>
<span class="hljs-string"><span</span> <span class="hljs-string">class="hljs-attr">on:</span></span>
<span class="hljs-string"><span</span> <span class="hljs-string">class="hljs-attr">push:</span></span>
<span class="hljs-string"><span</span> <span class="hljs-string">class="hljs-attr">branches:</span></span> [<span class="hljs-string"><span</span> <span class="hljs-string">class="hljs-string">main</span></span>]
<span class="hljs-string"><span</span> <span class="hljs-string">class="hljs-attr">pull_request:</span></span>
<span class="hljs-string"><span</span> <span class="hljs-string">class="hljs-attr">branches:</span></span> [<span class="hljs-string"><span</span> <span class="hljs-string">class="hljs-string">main</span></span>]
<span class="hljs-string"><span</span> <span class="hljs-string">class="hljs-attr">jobs:</span></span>
<span class="hljs-string"><span</span> <span class="hljs-string">class="hljs-attr">test:</span></span>
<span class="hljs-string"><span</span> <span class="hljs-string">class="hljs-attr">runs-on:</span></span> <span class="hljs-string"><span</span> <span class="hljs-string">class="hljs-string">ubuntu-latest</span></span>
<span class="hljs-string"><span</span> <span class="hljs-string">class="hljs-attr">steps:</span></span>
<span class="hljs-string"><span</span> <span class="hljs-string">class="hljs-bullet">-</span></span> <span class="hljs-string"><span</span> <span class="hljs-string">class="hljs-attr">uses:</span></span> <span class="hljs-string"><span</span> <span class="hljs-string">class="hljs-string">actions/checkout@v3</span></span>
<span class="hljs-string"><span</span> <span class="hljs-string">class="hljs-bullet">-</span></span> <span class="hljs-string"><span</span> <span class="hljs-string">class="hljs-attr">uses:</span></span> <span class="hljs-string"><span</span> <span class="hljs-string">class="hljs-string">actions/setup-node@v3</span></span>
<span class="hljs-string"><span</span> <span class="hljs-string">class="hljs-attr">with:</span></span>
<span class="hljs-string"><span</span> <span class="hljs-string">class="hljs-attr">node-version:</span></span> <span class="hljs-string"><span</span> <span class="hljs-string">class="hljs-string">&#x27;20&#x27;</span></span>
<span class="hljs-string"><span</span> <span class="hljs-string">class="hljs-bullet">-</span></span> <span class="hljs-string"><span</span> <span class="hljs-string">class="hljs-attr">run:</span></span> <span class="hljs-string"><span</span> <span class="hljs-string">class="hljs-string">npm</span></span> <span class="hljs-string"><span</span> <span class="hljs-string">class="hljs-string">ci</span></span>
<span class="hljs-string"><span</span> <span class="hljs-string">class="hljs-bullet">-</span></span> <span class="hljs-string"><span</span> <span class="hljs-string">class="hljs-attr">run:</span></span> <span class="hljs-string"><span</span> <span class="hljs-string">class="hljs-string">npm</span></span> <span class="hljs-string"><span</span> <span class="hljs-string">class="hljs-string">run</span></span> <span class="hljs-string"><span</span> <span class="hljs-string">class="hljs-string">lint</span></span>
<span class="hljs-string"><span</span> <span class="hljs-string">class="hljs-bullet">-</span></span> <span class="hljs-string"><span</span> <span class="hljs-string">class="hljs-attr">run:</span></span> <span class="hljs-string"><span</span> <span class="hljs-string">class="hljs-string">npm</span></span> <span class="hljs-string"><span</span> <span class="hljs-string">class="hljs-string">run</span></span> <span class="hljs-string"><span</span> <span class="hljs-string">class="hljs-string">typecheck</span></span>
<span class="hljs-string"><span</span> <span class="hljs-string">class="hljs-bullet">-</span></span> <span class="hljs-string"><span</span> <span class="hljs-string">class="hljs-attr">run:</span></span> <span class="hljs-string"><span</span> <span class="hljs-string">class="hljs-string">npm</span></span> <span class="hljs-string"><span</span> <span class="hljs-string">class="hljs-string">run</span></span> <span class="hljs-string"><span</span> <span class="hljs-string">class="hljs-string">test</span></span>
<span class="hljs-string"><span</span> <span class="hljs-string">class="hljs-bullet">-</span></span> <span class="hljs-string"><span</span> <span class="hljs-string">class="hljs-attr">run:</span></span> <span class="hljs-string"><span</span> <span class="hljs-string">class="hljs-string">npm</span></span> <span class="hljs-string"><span</span> <span class="hljs-string">class="hljs-string">run</span></span> <span class="hljs-string"><span</span> <span class="hljs-string">class="hljs-string">build</span></span>
<span class="hljs-string"><span</span> <span class="hljs-string">class="hljs-attr">deploy:</span></span>
<span class="hljs-string"><span</span> <span class="hljs-string">class="hljs-attr">needs:</span></span> <span class="hljs-string"><span</span> <span class="hljs-string">class="hljs-string">test</span></span>
<span class="hljs-string"><span</span> <span class="hljs-string">class="hljs-attr">if:</span></span> <span class="hljs-string"><span</span> <span class="hljs-string">class="hljs-string">github.ref</span></span> <span class="hljs-string"><span</span> <span class="hljs-string">class="hljs-string">==</span></span> <span class="hljs-string"><span</span> <span class="hljs-string">class="hljs-string">&#x27;refs/heads/main&#x27;</span></span>
<span class="hljs-string"><span</span> <span class="hljs-string">class="hljs-attr">runs-on:</span></span> <span class="hljs-string"><span</span> <span class="hljs-string">class="hljs-string">ubuntu-latest</span></span>
<span class="hljs-string"><span</span> <span class="hljs-string">class="hljs-attr">steps:</span></span>
<span class="hljs-string"><span</span> <span class="hljs-string">class="hljs-bullet">-</span></span> <span class="hljs-string"><span</span> <span class="hljs-string">class="hljs-attr">name:</span></span> <span class="hljs-string"><span</span> <span class="hljs-string">class="hljs-string">Deploy</span></span> <span class="hljs-string"><span</span> <span class="hljs-string">class="hljs-string">to</span></span> <span class="hljs-string"><span</span> <span class="hljs-string">class="hljs-string">production</span></span>
<span class="hljs-string"><span</span> <span class="hljs-string">class="hljs-attr">run:</span></span> <span class="hljs-string"><span</span> <span class="hljs-string">class="hljs-string">|</span></span>
<span class="hljs-string"><span</span> <span class="hljs-string">class="hljs-comment">#</span> <span class="hljs-string">Deploy</span> <span class="hljs-string">script</span> <span class="hljs-string">here</span></span>
Pipeline mínimo obligatorio:
- Linting (ESLint)
- Type checking (TypeScript)
- Tests (Jest, Vitest)
- Build (asegurar que compila)
- Deploy (solo si todo pasa)
Kubernetes: Orquestación para scale
Para aplicaciones que crecen:
<span class="hljs-string"><span</span> <span class="hljs-string">class="hljs-comment">#</span> <span class="hljs-string">deployment.yaml</span></span>
<span class="hljs-string"><span</span> <span class="hljs-string">class="hljs-attr">apiVersion:</span></span> <span class="hljs-string"><span</span> <span class="hljs-string">class="hljs-string">apps/v1</span></span>
<span class="hljs-string"><span</span> <span class="hljs-string">class="hljs-attr">kind:</span></span> <span class="hljs-string"><span</span> <span class="hljs-string">class="hljs-string">Deployment</span></span>
<span class="hljs-string"><span</span> <span class="hljs-string">class="hljs-attr">metadata:</span></span>
<span class="hljs-string"><span</span> <span class="hljs-string">class="hljs-attr">name:</span></span> <span class="hljs-string"><span</span> <span class="hljs-string">class="hljs-string">web-app</span></span>
<span class="hljs-string"><span</span> <span class="hljs-string">class="hljs-attr">spec:</span></span>
<span class="hljs-string"><span</span> <span class="hljs-string">class="hljs-attr">replicas:</span></span> <span class="hljs-string"><span</span> <span class="hljs-string">class="hljs-number">3</span></span> <span class="hljs-string"><span</span> <span class="hljs-string">class="hljs-comment">#</span> <span class="hljs-string">Alta</span> <span class="hljs-string">disponibilidad</span></span>
<span class="hljs-string"><span</span> <span class="hljs-string">class="hljs-attr">selector:</span></span>
<span class="hljs-string"><span</span> <span class="hljs-string">class="hljs-attr">matchLabels:</span></span>
<span class="hljs-string"><span</span> <span class="hljs-string">class="hljs-attr">app:</span></span> <span class="hljs-string"><span</span> <span class="hljs-string">class="hljs-string">web-app</span></span>
<span class="hljs-string"><span</span> <span class="hljs-string">class="hljs-attr">template:</span></span>
<span class="hljs-string"><span</span> <span class="hljs-string">class="hljs-attr">metadata:</span></span>
<span class="hljs-string"><span</span> <span class="hljs-string">class="hljs-attr">labels:</span></span>
<span class="hljs-string"><span</span> <span class="hljs-string">class="hljs-attr">app:</span></span> <span class="hljs-string"><span</span> <span class="hljs-string">class="hljs-string">web-app</span></span>
<span class="hljs-string"><span</span> <span class="hljs-string">class="hljs-attr">spec:</span></span>
<span class="hljs-string"><span</span> <span class="hljs-string">class="hljs-attr">containers:</span></span>
<span class="hljs-string"><span</span> <span class="hljs-string">class="hljs-bullet">-</span></span> <span class="hljs-string"><span</span> <span class="hljs-string">class="hljs-attr">name:</span></span> <span class="hljs-string"><span</span> <span class="hljs-string">class="hljs-string">web-app</span></span>
<span class="hljs-string"><span</span> <span class="hljs-string">class="hljs-attr">image:</span></span> <span class="hljs-string"><span</span> <span class="hljs-string">class="hljs-string">myapp:latest</span></span>
<span class="hljs-string"><span</span> <span class="hljs-string">class="hljs-attr">ports:</span></span>
<span class="hljs-string"><span</span> <span class="hljs-string">class="hljs-bullet">-</span></span> <span class="hljs-string"><span</span> <span class="hljs-string">class="hljs-attr">containerPort:</span></span> <span class="hljs-string"><span</span> <span class="hljs-string">class="hljs-number">3000</span></span>
<span class="hljs-string"><span</span> <span class="hljs-string">class="hljs-attr">resources:</span></span>
<span class="hljs-string"><span</span> <span class="hljs-string">class="hljs-attr">requests:</span></span>
<span class="hljs-string"><span</span> <span class="hljs-string">class="hljs-attr">memory:</span></span> <span class="hljs-string"><span</span> <span class="hljs-string">class="hljs-string">&quot;256Mi&quot;</span></span>
<span class="hljs-string"><span</span> <span class="hljs-string">class="hljs-attr">cpu:</span></span> <span class="hljs-string"><span</span> <span class="hljs-string">class="hljs-string">&quot;250m&quot;</span></span>
<span class="hljs-string"><span</span> <span class="hljs-string">class="hljs-attr">limits:</span></span>
<span class="hljs-string"><span</span> <span class="hljs-string">class="hljs-attr">memory:</span></span> <span class="hljs-string"><span</span> <span class="hljs-string">class="hljs-string">&quot;512Mi&quot;</span></span>
<span class="hljs-string"><span</span> <span class="hljs-string">class="hljs-attr">cpu:</span></span> <span class="hljs-string"><span</span> <span class="hljs-string">class="hljs-string">&quot;500m&quot;</span></span>
Cuándo introducir Kubernetes:
- Múltiples microservicios
- Necesitas auto-scaling
- Alta disponibilidad crítica
- Tráfico >10.000 usuarios/día
Para proyectos pequeños-medianos, Docker + VPS es suficiente.
Inteligencia Artificial: El diferenciador 2026
El programador web que ignora IA está obsoleto.
LangChain: Framework para apps con LLMs
Integración de IA generativa:
<span <span class="hljs-keyword">class</span>=<span class="hljs-string">"hljs-keyword"</span>><span class="hljs-keyword">from</span></span> langchain.chat_models <span <span class="hljs-keyword">class</span>=<span class="hljs-string">"hljs-keyword"</span>><span class="hljs-keyword">import</span></span> ChatOpenAI
<span <span class="hljs-keyword">class</span>=<span class="hljs-string">"hljs-keyword"</span>><span class="hljs-keyword">from</span></span> langchain.chains <span <span class="hljs-keyword">class</span>=<span class="hljs-string">"hljs-keyword"</span>><span class="hljs-keyword">import</span></span> ConversationalRetrievalChain
<span <span class="hljs-keyword">class</span>=<span class="hljs-string">"hljs-keyword"</span>><span class="hljs-keyword">from</span></span> langchain.vectorstores <span <span class="hljs-keyword">class</span>=<span class="hljs-string">"hljs-keyword"</span>><span class="hljs-keyword">import</span></span> Chroma
<span <span class="hljs-keyword">class</span>=<span class="hljs-string">"hljs-comment"</span>><span class="hljs-comment"># Sistema RAG para chatbot con conocimiento empresarial</span></span>
llm = ChatOpenAI(model=<span <span class="hljs-keyword">class</span>=<span class="hljs-string">"hljs-string"</span>>&quot;gpt-<span class="hljs-number">4</span>&quot;</span>, temperature=<span <span class="hljs-keyword">class</span>=<span class="hljs-string">"hljs-number"</span>><span class="hljs-number">0</span></span>)
vectorstore = Chroma(
persist_directory=<span <span class="hljs-keyword">class</span>=<span class="hljs-string">"hljs-string"</span>>&quot;./data/vectorstore&quot;</span>,
embedding_function=OpenAIEmbeddings()
)
qa_chain = ConversationalRetrievalChain.from_llm(
llm=llm,
retriever=vectorstore.as_retriever(),
return_source_documents=<span <span class="hljs-keyword">class</span>=<span class="hljs-string">"hljs-literal"</span>><span class="hljs-literal">True</span></span>
)
response = qa_chain({
<span <span class="hljs-keyword">class</span>=<span class="hljs-string">"hljs-string"</span>>&quot;question&quot;</span>: <span <span class="hljs-keyword">class</span>=<span class="hljs-string">"hljs-string"</span>>&quot;¿Cuál es nuestra política de devoluciones?&quot;</span>,
<span <span class="hljs-keyword">class</span>=<span class="hljs-string">"hljs-string"</span>>&quot;chat_history&quot;</span>: []
})
Uso LangChain en todos mis proyectos de IA, desde chatbots hasta sistemas RAG empresariales.
Modelos y APIs
Ecosistema actual:
- OpenAI (GPT-4, GPT-4o): Calidad líder
- Anthropic (Claude): Reasoning superior
- Google (Gemini): Multimodal potente
- Open source (Llama, Mistral): Control y privacidad
Casos de uso prácticos
- Chatbots inteligentes: Atención al cliente 24/7
- Sistemas RAG: Consultas sobre documentación
- Análisis de texto: Clasificación, sentiment, resumen
- Computer Vision: Detección de objetos, OCR
- Agentes autónomos: Automatización compleja
Mi stack personal como programador web
Después de 33 años, este es mi stack profesional:
Frontend
- React + Next.js + TypeScript: 90% de proyectos
- Tailwind CSS: Styling rápido y consistente
- React Query: State management server
- Zustand: State management cliente
Backend
- Node.js + Express: APIs rápidas
- Python + FastAPI: Proyectos con IA
- PHP + Symfony: Clientes legacy
Databases
- PostgreSQL: Default para datos relacionales
- Redis: Cache y sessions
- MongoDB: Casos específicos
DevOps
- Docker: Todos los proyectos
- GitHub Actions: CI/CD
- OVH VPS: Hosting confiable y económico
AI/ML
- LangChain: Framework principal
- OpenAI API: GPT-4 para calidad
- Pinecone: Vector database
- Hugging Face: Modelos open source
Herramientas de desarrollo
Editor: VSCode con extensiones:
- ESLint, Prettier (formatting automático)
- TypeScript + Pylance (type checking)
- GitHub Copilot (productividad)
- Thunder Client (testing APIs)
Terminal: Zsh con Oh My Zsh Git UI: GitKraken o Sourcetree Database UI: DBeaver o TablePlus REST client: Insomnia o Thunder Client
Cómo aprender el stack moderno
Roadmap sugerido para aspirantes a programador web:
Fundamentos (2-3 meses)
- HTML, CSS, JavaScript sólidos
- Git y control de versiones
- Command line básico
Frontend moderno (3-4 meses)
- React con hooks
- TypeScript
- Next.js
- Tailwind CSS
Backend y APIs (3-4 meses)
- Node.js o Python
- REST APIs
- PostgreSQL
- Authentication/Authorization
DevOps básico (2-3 meses)
- Docker
- CI/CD con GitHub Actions
- Deployment (Vercel, Railway, VPS)
Testing (continuamente)
- Jest/Vitest
- React Testing Library
- E2E con Playwright
IA (opcional pero recomendado)
- LangChain basics
- OpenAI API
- RAG systems
Total: 12-18 meses para ser programador web competente
Con dedicación, práctica y proyectos reales.
Conclusión: Stack al servicio del negocio
El stack tecnológico no es un fin en sí mismo. Es medio para:
- Resolver problemas de negocio
- Crear valor para usuarios
- Mantener código a largo plazo
- Iterar rápido sobre feedback
Los mejores programadores web:
- Eligen tecnologías por razones válidas, no por hype
- Balancean modernidad con estabilidad
- Priorizan DX para productividad
- Nunca dejan de aprender
Con 33 años de experiencia, he visto docenas de tecnologías ir y venir. Lo que permanece:
- Fundamentos sólidos (algoritmos, arquitectura, patterns)
- Calidad no negociable (TDD, code review, docs)
- Pragmatismo (usa tecnología apropiada, no la más cool)
- Aprendizaje continuo (el día que dejas de aprender, estás obsoleto)
¿Necesitas ayuda con tu proyecto? Ya sea web profesional, ecommerce, plataforma SaaS o aplicación con IA, mi stack moderno y experiencia están a tu servicio.
Presupuesto detallado en menos de 24h.
Jordi Morillo - Programador Web | Ver mi stack completo | TDD obligatorio | Garantía de por vida