Files
2026-08-28 10:11:11 -03:00

1271 lines
46 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="pt-BR">
<head>
<!-- Performance: Preconnect to critical origins -->
<link rel="preconnect" href="https://d3js.org" crossorigin>
<link rel="preconnect" href="https://images.pexels.com" crossorigin>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="icon" type="image/svg+xml" href="/favicon.svg">
<link rel="alternate icon" href="/favicon.ico">
<title>AWS Hosting Odoo Amazon Cloud 2025 | Odoo Expertos · PT</title>
<!-- Canonical URL -->
<link rel="canonical" href="https://www.odoo-expertos.com/pt/odoo-hosting/aws-hosting-odoo-amazon-cloud-2025/">
<!-- Meta tags -->
<meta name="description" content="Guía completa para implementar Odoo ERP en AWS. Arquitectura, migración, costos y mejores prácticas para hosting empresaria - AWS Hosting Odoo Amazon Cloud 2025 | PT">
<meta name="keywords" content="AWS hosting Odoo, Odoo Amazon Cloud, Odoo ERP AWS, implementación Odoo AWS, hosting empresarial">
<meta name="robots" content="noindex,follow">
<meta name="author" content="Odoo Expertos">
<!-- Open Graph Meta Tags -->
<meta property="og:title" content="AWS Hosting para Odoo ERP - Guía Completa 2025">
<meta property="og:description" content="Implementa Odoo en AWS con alta disponibilidad y escalabilidad. Arquitectura, costos y mejores prácticas.">
<meta property="og:type" content="article">
<meta property="og:url" content="https://www.odoo-expertos.com/pt/odoo-hosting/aws-hosting-odoo-amazon-cloud-2025/">
<meta property="og:site_name" content="Odoo Expertos">
<meta property="og:locale" content="pt_BR">
<!-- Twitter Card Meta Tags -->
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:title" content="AWS Hosting para Odoo ERP - Guía Completa 2025">
<meta name="twitter:description" content="Implementa Odoo en AWS con alta disponibilidad y escalabilidad.">
<!-- Schema.org structured data -->
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "Article",
"headline": "AWS Hosting para Odoo ERP - Implementación en Amazon Cloud 2025",
"author": {
"@type": "Organization",
"name": "Odoo Expertos"
},
"datePublished": "2025-01-15",
"dateModified": "2025-01-27",
"publisher": {
"@type": "Organization",
"name": "Odoo Expertos",
"logo": {
"@type": "ImageObject",
"url": "https://www.odoo-expertos.com/assets/logo.png"
}
}
}
</script>
<link rel="stylesheet" href="/css/main.min.css">
<style>
/* Article-specific styles */
body {
background: #1a1a1a;
color: #e0e0e0;
font-family: 'Inter', sans-serif;
margin: 0;
padding: 0;
}
.article-content {
max-width: 1200px;
margin: 0 auto;
padding: 2rem;
}
/* Hero section */
.hero-section {
background: linear-gradient(135deg, #2a2a2a 0%, #1a1a1a 100%);
padding: 4rem 2rem;
margin-bottom: 3rem;
border-bottom: 3px solid #FF6B35;
text-align: center;
}
.hero-section h1 {
color: #FF6B35;
font-size: 2.5rem;
margin-bottom: 1rem;
line-height: 1.2;
}
.hero-section .text-accent {
color: #FF8A50;
}
.hero-subtitle {
font-size: 1.25rem;
line-height: 1.6;
color: #e0e0e0;
max-width: 800px;
margin: 0 auto 2rem;
}
/* Hero stats */
.hero-stats {
display: flex;
justify-content: center;
gap: 2rem;
margin: 2rem 0;
flex-wrap: wrap;
}
.stat-card {
background: #2a2a2a;
padding: 1.5rem;
border-radius: 8px;
border: 1px solid #3a3a3a;
min-width: 150px;
}
.stat-value {
font-size: 2rem;
font-weight: 700;
color: #FF6B35;
}
.stat-label {
color: #999;
font-size: 0.9rem;
margin-top: 0.5rem;
}
/* Content sections */
.content-section {
background: #2a2a2a;
padding: 2rem;
margin-bottom: 2rem;
border-radius: 8px;
border: 1px solid #3a3a3a;
}
.section-header {
text-align: center;
margin-bottom: 3rem;
}
.section-title {
color: #FF6B35;
font-size: 2rem;
margin-bottom: 1rem;
}
.section-subtitle {
color: #e0e0e0;
font-size: 1.1rem;
opacity: 0.9;
}
/* Features grid */
.features-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: 2rem;
margin-top: 2rem;
}
.feature-card {
background: #3a3a3a;
padding: 2rem;
border-radius: 8px;
text-align: center;
transition: transform 0.3s ease;
}
.feature-card:hover {
transform: translateY(-5px);
}
.feature-icon {
width: 60px;
height: 60px;
margin: 0 auto 1rem;
color: #FF6B35;
}
.feature-title {
color: #FF8A50;
font-size: 1.25rem;
margin-bottom: 1rem;
}
.feature-description {
color: #e0e0e0;
line-height: 1.6;
}
/* Architecture components */
.architecture-content {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 2rem;
align-items: start;
}
.component-list {
display: flex;
flex-direction: column;
gap: 1rem;
}
.component-item {
background: #3a3a3a;
padding: 1rem;
border-radius: 4px;
border-left: 3px solid #FF6B35;
}
.component-item h4 {
color: #FF8A50;
margin: 0 0 0.5rem 0;
}
.component-item p {
margin: 0;
color: #e0e0e0;
}
/* Migration steps */
.migration-steps {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: 2rem;
margin-top: 2rem;
}
.step-card {
background: #3a3a3a;
padding: 1.5rem;
border-radius: 8px;
position: relative;
}
.step-number {
position: absolute;
top: -15px;
left: 20px;
background: #FF6B35;
color: #1a1a1a;
width: 30px;
height: 30px;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
font-weight: 700;
}
.step-card h3 {
color: #FF8A50;
margin-top: 1rem;
margin-bottom: 1rem;
}
.step-card ul {
margin: 0;
padding-left: 1.5rem;
}
.step-card li {
color: #e0e0e0;
margin-bottom: 0.5rem;
}
/* Cost table */
.cost-table {
background: #3a3a3a;
padding: 1.5rem;
border-radius: 8px;
margin-top: 1rem;
}
.cost-row {
display: flex;
justify-content: space-between;
padding: 0.75rem 0;
border-bottom: 1px solid #4a4a4a;
}
.cost-row:last-child {
border-bottom: none;
font-weight: 700;
color: #FF6B35;
padding-top: 1rem;
}
.cost-item {
color: #e0e0e0;
}
.cost-value {
color: #FF8A50;
}
/* Best practices grid */
.practices-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: 2rem;
margin-top: 2rem;
}
.practice-card {
background: #3a3a3a;
padding: 1.5rem;
border-radius: 8px;
}
.practice-card h3 {
color: #FF8A50;
margin-bottom: 1rem;
}
.practice-card ul {
margin: 0;
padding-left: 1.5rem;
}
.practice-card li {
color: #e0e0e0;
margin-bottom: 0.5rem;
}
/* Visualization containers */
.visual-container {
background: #2a2a2a;
padding: 2rem;
margin: 2rem 0;
border-radius: 8px;
border: 1px solid #3a3a3a;
}
.visual-title {
color: #FF6B35;
font-size: 1.25rem;
margin-bottom: 1rem;
text-align: center;
}
.chart-container {
width: 100%;
height: 400px;
position: relative;
}
/* Links */
a {
color: #FF6B35;
text-decoration: none;
transition: color 0.3s ease;
}
a:hover {
color: #FFB74D;
}
/* Buttons */
.btn {
display: inline-block;
padding: 0.75rem 1.5rem;
border-radius: 4px;
font-weight: 600;
text-align: center;
transition: all 0.3s ease;
margin: 0.5rem;
}
.btn-primary {
background: #FF6B35;
color: #1a1a1a;
}
.btn-primary:hover {
background: #FF8A50;
transform: translateY(-2px);
}
.btn-outline {
border: 2px solid #FF6B35;
color: #FF6B35;
}
.btn-outline:hover {
background: #FF6B35;
color: #1a1a1a;
}
.btn-large {
padding: 1rem 2rem;
font-size: 1.1rem;
}
/* CTA section */
.cta-section {
background: linear-gradient(135deg, #FF6B35 0%, #FF8A50 100%);
padding: 3rem 2rem;
margin: 3rem 0;
border-radius: 8px;
text-align: center;
}
.cta-title {
color: #1a1a1a;
font-size: 2rem;
margin-bottom: 1rem;
}
.cta-subtitle {
color: #1a1a1a;
font-size: 1.1rem;
margin-bottom: 2rem;
opacity: 0.9;
}
.cta-actions {
display: flex;
justify-content: center;
gap: 1rem;
flex-wrap: wrap;
}
/* Breadcrumbs */
.breadcrumbs {
padding: 1rem 0;
margin-bottom: 2rem;
font-size: 0.875rem;
}
.breadcrumb-list {
display: flex;
align-items: center;
list-style: none;
margin: 0;
padding: 0;
flex-wrap: wrap;
}
.breadcrumb-item {
display: inline;
}
.breadcrumb-item a {
color: #999;
text-decoration: none;
transition: color 0.3s ease;
}
.breadcrumb-item a:hover {
color: #FF6B35;
}
.breadcrumb-separator {
margin: 0 0.5rem;
color: #666;
}
.breadcrumb-item.active {
color: #e0e0e0;
}
.container {
max-width: 1200px;
margin: 0 auto;
padding: 0 2rem;
}
/* Responsive */
@media (max-width: 768px) {
.hero-section h1 {
font-size: 2rem;
}
.hero-stats {
flex-direction: column;
align-items: center;
}
.architecture-content {
grid-template-columns: 1fr;
}
.article-content {
padding: 1rem;
}
.content-section {
padding: 1.5rem;
}
}
</style>
</head>
<body>
<script src="/components/header.min.js"></script>
<script>document.write(/*W6-static*/null);</script>
<!-- Breadcrumbs -->
<nav class="breadcrumbs" aria-label="Breadcrumb">
<div class="container">
<ol class="breadcrumb-list">
<li class="breadcrumb-item"><a href="/">Inicio</a></li>
<li class="breadcrumb-separator"></li>
<li class="breadcrumb-item"><a href="/pt/odoo-hosting/">Odoo Hosting</a></li>
<li class="breadcrumb-separator"></li>
<li class="breadcrumb-item active" aria-current="page">AWS Hosting para Odoo ERP</li>
</ol>
</div>
</nav>
<div class="article-content">
<!-- Hero Section -->
<section class="hero-section">
<h1>AWS Hosting para <span class="text-accent">Odoo ERP</span></h1>
<p class="hero-subtitle">
Implementación empresarial en Amazon Cloud con alta disponibilidad,
escalabilidad automática y arquitectura optimizada para Odoo. Descubre por qué
AWS es la <a href="/pt/odoo-hosting/hosting-odoo-completo-guia-2025/" rel="internal">solución de hosting completa</a>
preferida por empresas Fortune 500 para sus sistemas ERP.
</p>
<div class="hero-stats">
<div class="stat-card">
<div class="stat-value">99.99%</div>
<div class="stat-label">Uptime SLA</div>
</div>
<div class="stat-card">
<div class="stat-value">25+</div>
<div class="stat-label">Regiones AWS</div>
</div>
<div class="stat-card">
<div class="stat-value">Auto</div>
<div class="stat-label">Escalabilidad</div>
</div>
</div>
</section>
<!-- Introduction Section -->
<section class="content-section">
<div class="section-header">
<h2 class="section-title">Por qué elegir AWS para Odoo</h2>
<p class="section-subtitle">
Amazon Web Services ofrece la infraestructura más completa y confiable
para implementaciones empresariales de Odoo ERP
</p>
</div>
<div class="features-grid">
<div class="feature-card">
<div class="feature-icon">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M12 2L2 7L12 12L22 7L12 2Z"></path>
<path d="M2 17L12 22L22 17"></path>
<path d="M2 12L12 17L22 12"></path>
</svg>
</div>
<h3 class="feature-title">Infraestructura Global</h3>
<p class="feature-description">
25+ regiones con múltiples zonas de disponibilidad para máxima redundancia
</p>
</div>
<div class="feature-card">
<div class="feature-icon">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<rect x="4" y="4" width="16" height="16" rx="2" ry="2"></rect>
<rect x="9" y="9" width="6" height="6"></rect>
<line x1="9" y1="1" x2="9" y2="4"></line>
<line x1="15" y1="1" x2="15" y2="4"></line>
<line x1="9" y1="20" x2="9" y2="23"></line>
<line x1="15" y1="20" x2="15" y2="23"></line>
<line x1="20" y1="9" x2="23" y2="9"></line>
<line x1="20" y1="14" x2="23" y2="14"></line>
<line x1="1" y1="9" x2="4" y2="9"></line>
<line x1="1" y1="14" x2="4" y2="14"></line>
</svg>
</div>
<h3 class="feature-title">Escalabilidad Automática</h3>
<p class="feature-description">
Auto Scaling Groups que ajustan recursos según demanda en tiempo real
</p>
</div>
<div class="feature-card">
<div class="feature-icon">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"></path>
<path d="M9 12l2 2 4-4"></path>
</svg>
</div>
<h3 class="feature-title">Seguridad Enterprise</h3>
<p class="feature-description">
Certificaciones ISO, SOC, PCI-DSS con encriptación en reposo y tránsito
</p>
</div>
</div>
</section>
<!-- Architecture Section -->
<section class="content-section">
<div class="section-header">
<h2 class="section-title">Arquitectura AWS para Odoo</h2>
<p class="section-subtitle">
Diseño de alta disponibilidad con componentes AWS optimizados para Odoo ERP
</p>
</div>
<div class="architecture-content">
<div class="visual-container">
<h3 class="visual-title">Ecosistema AWS para Odoo</h3>
<div id="aws-ecosystem" class="chart-container"></div>
</div>
<div class="architecture-components">
<h3>Componentes Principales</h3>
<div class="component-list">
<div class="component-item">
<h4>EC2 Instances</h4>
<p>Servidores optimizados para Odoo con tipos de instancia m5.xlarge o superiores.
Conoce todos los <a href="/pt/odoo/instalar-odoo-guia-paso-a-paso-2025/" rel="internal">requisitos para instalar Odoo</a>
correctamente en la nube.</p>
</div>
<div class="component-item">
<h4>RDS PostgreSQL</h4>
<p>Base de datos gestionada con Multi-AZ para alta disponibilidad</p>
</div>
<div class="component-item">
<h4>ELB + Auto Scaling</h4>
<p>Balanceador de carga con escalado automático según métricas</p>
</div>
<div class="component-item">
<h4>S3 + CloudFront</h4>
<p>Almacenamiento de archivos y CDN global para assets estáticos</p>
</div>
</div>
</div>
</div>
</section>
<!-- Migration Process -->
<section class="content-section">
<div class="section-header">
<h2 class="section-title">Proceso de Migración a AWS</h2>
<p class="section-subtitle">
Plan detallado para migrar Odoo a AWS sin interrupciones
</p>
</div>
<div class="visual-container">
<h3 class="visual-title">Timeline de Migración</h3>
<div id="migration-timeline" class="chart-container"></div>
</div>
<div class="migration-steps">
<div class="step-card">
<div class="step-number">1</div>
<h3>Análisis y Planificación</h3>
<ul>
<li>Auditoría de infraestructura actual</li>
<li>Dimensionamiento de recursos AWS comparado con <a href="/pt/odoo-hosting/vps-hosting-odoo-servidor-virtual-2025/" rel="internal">opciones VPS tradicionales</a></li>
<li>Plan de migración detallado</li>
</ul>
</div>
<div class="step-card">
<div class="step-number">2</div>
<h3>Preparación AWS</h3>
<ul>
<li>Configuración de VPC y subredes</li>
<li>Setup de RDS PostgreSQL</li>
<li>Configuración de seguridad</li>
</ul>
</div>
<div class="step-card">
<div class="step-number">3</div>
<h3>Migración de Datos</h3>
<ul>
<li>Backup completo de Odoo</li>
<li>Migración de base de datos</li>
<li>Sincronización de archivos a S3</li>
</ul>
</div>
<div class="step-card">
<div class="step-number">4</div>
<h3>Go Live y Optimización</h3>
<ul>
<li>Cambio de DNS</li>
<li>Monitoreo post-migración</li>
<li>Optimización de performance</li>
</ul>
</div>
</div>
</section>
<!-- Cost Comparison -->
<section class="content-section">
<div class="section-header">
<h2 class="section-title">Comparativa de Costos</h2>
<p class="section-subtitle">
Análisis detallado de costos AWS vs otras opciones de hosting como
<a href="/pt/odoo-hosting/azure-hosting-odoo-microsoft-2025/" rel="internal">Azure</a> y
<a href="/pt/odoo-hosting/digitalocean-hosting-odoo-deployment-2025/" rel="internal">DigitalOcean</a>
</p>
</div>
<div class="visual-container">
<h3 class="visual-title">Matriz de Comparación</h3>
<div id="hosting-comparison" class="chart-container"></div>
</div>
<div class="cost-breakdown">
<h3>Desglose de Costos AWS (Estimado Mensual)</h3>
<div class="cost-table">
<div class="cost-row">
<span class="cost-item">EC2 (2x m5.xlarge)</span>
<span class="cost-value">$320</span>
</div>
<div class="cost-row">
<span class="cost-item">RDS PostgreSQL Multi-AZ</span>
<span class="cost-value">$280</span>
</div>
<div class="cost-row">
<span class="cost-item">Application Load Balancer</span>
<span class="cost-value">$25</span>
</div>
<div class="cost-row">
<span class="cost-item">S3 Storage (500GB)</span>
<span class="cost-value">$12</span>
</div>
<div class="cost-row">
<span class="cost-item">CloudFront CDN</span>
<span class="cost-value">$50</span>
</div>
<div class="cost-row">
<span class="cost-item">Data Transfer</span>
<span class="cost-value">$90</span>
</div>
<div class="cost-row">
<span class="cost-item">Total Estimado</span>
<span class="cost-value">$777/mes</span>
</div>
</div>
</div>
</section>
<!-- Best Practices -->
<section class="content-section">
<div class="section-header">
<h2 class="section-title">Mejores Prácticas AWS para Odoo</h2>
<p class="section-subtitle">
Configuraciones recomendadas para máximo rendimiento y seguridad
</p>
</div>
<div class="practices-grid">
<div class="practice-card">
<h3>Performance</h3>
<ul>
<li>Usar instancias optimizadas para memoria</li>
<li>ElastiCache para sesiones</li>
<li>CloudFront para assets estáticos</li>
<li>Auto Scaling basado en CPU. Para proyectos enterprise, considera también
<a href="/pt/odoo-hosting/hosting-odoo-enterprise-empresarial-2025/" rel="internal">hosting enterprise dedicado</a></li>
</ul>
</div>
<div class="practice-card">
<h3>Seguridad</h3>
<ul>
<li>VPC con subredes privadas</li>
<li>Security Groups restrictivos</li>
<li>Encriptación con KMS</li>
<li>IAM roles granulares</li>
</ul>
</div>
<div class="practice-card">
<h3>Backups</h3>
<ul>
<li>Snapshots automáticos RDS</li>
<li>Lifecycle policies en S3</li>
<li>Cross-region replication</li>
<li>Disaster recovery plan</li>
</ul>
</div>
</div>
</section>
<!-- CTA Section -->
<section class="cta-section">
<h2 class="cta-title">¿Listo para migrar Odoo a AWS?</h2>
<p class="cta-subtitle">
Nuestro equipo de expertos certificados AWS puede ayudarte con la implementación.
Conoce más sobre <a href="https://aws.amazon.com/odoo/" target="_blank" rel="nofollow noopener">AWS para aplicaciones empresariales</a>.
</p>
<div class="cta-actions">
<a href="#contacto" class="btn btn-primary btn-large">
Solicitar Consultoría
</a>
<a href="/recursos/guia-aws-odoo.pdf" class="btn btn-outline btn-large">
Descargar Guía PDF
</a>
</div>
</section>
</div>
<!-- ANIMATED HOSTING BANNER - A/B Testing Variation 1 -->
<script src="/components/hosting-banner-variations.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/7.8.5/d3.min.js"></script>
<script>
// Insert animated banner variation 1
if (window.location.pathname.includes('/odoo-hosting/')) {
document.write(createAnimatedHostingBannerVariation(1));
// Initialize D3 animations after banner is inserted
document.addEventListener('DOMContentLoaded', function() {
const bannerId = document.querySelector('.animated-hosting-banner-wrapper')?.id;
if (bannerId && typeof initializeBannerAnimations === 'function') {
// D3 animations would initialize here if defined
}
});
}
</script>
<script src="/components/eeat.min.js"></script>
<script>
document.write(createEEAT({
author: {
name: "Equipo Odoo Expertos",
title: "Expertos en Infraestructura Cloud",
experience: "10+ años implementando Odoo en AWS"
},
publishDate: "15 de enero de 2025",
modifiedDate: "27 de enero de 2025"
}));
</script>
<script src="/components/footer.min.js"></script>
<script>document.write(/*W6-static*/null);</script>
<script src="/js/cookie-banner.min.js"></script>
<!-- D3.js library -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/7.8.5/d3.min.js"></script>
<script>
// Initialize banner animations after D3 is loaded
document.addEventListener('DOMContentLoaded', function() {
setTimeout(() => {
const bannerId = document.querySelector('.animated-hosting-banner-wrapper')?.id;
if (bannerId && typeof initializeBannerAnimations === 'function') {
initializeBannerAnimations(bannerId);
}
}, 100);
});
</script>
<script>
// AWS Ecosystem Force Network
function createAWSEcosystem() {
const container = d3.select("#aws-ecosystem");
const width = container.node().getBoundingClientRect().width;
const height = 400;
container.selectAll("*").remove();
const svg = container.append("svg")
.attr("width", width)
.attr("height", height)
.attr("viewBox", [0, 0, width, height]);
// AWS Services data
const nodes = [
{id: "Odoo", group: 1, size: 40},
{id: "EC2", group: 2, size: 35},
{id: "RDS", group: 2, size: 35},
{id: "ELB", group: 2, size: 30},
{id: "S3", group: 3, size: 30},
{id: "CloudFront", group: 3, size: 25},
{id: "Route53", group: 3, size: 25},
{id: "VPC", group: 4, size: 25},
{id: "IAM", group: 4, size: 20},
{id: "CloudWatch", group: 4, size: 20},
{id: "Auto Scaling", group: 2, size: 25},
{id: "ElasticCache", group: 3, size: 20}
];
const links = [
{source: "Odoo", target: "EC2", strength: 3},
{source: "Odoo", target: "RDS", strength: 3},
{source: "EC2", target: "ELB", strength: 2},
{source: "EC2", target: "Auto Scaling", strength: 2},
{source: "Odoo", target: "S3", strength: 2},
{source: "S3", target: "CloudFront", strength: 2},
{source: "ELB", target: "Route53", strength: 2},
{source: "EC2", target: "VPC", strength: 1},
{source: "RDS", target: "VPC", strength: 1},
{source: "EC2", target: "CloudWatch", strength: 1},
{source: "RDS", target: "CloudWatch", strength: 1},
{source: "Odoo", target: "ElasticCache", strength: 1},
{source: "VPC", target: "IAM", strength: 1}
];
// Color scale for dark theme
const color = d3.scaleOrdinal()
.domain([1, 2, 3, 4])
.range(["#FF9500", "#FF6B35", "#F7435F", "#7B68EE"]);
// Force simulation
const simulation = d3.forceSimulation(nodes)
.force("link", d3.forceLink(links).id(d => d.id).distance(80))
.force("charge", d3.forceManyBody().strength(-300))
.force("center", d3.forceCenter(width / 2, height / 2))
.force("collision", d3.forceCollide().radius(d => d.size + 5));
// Create links
const link = svg.append("g")
.selectAll("line")
.data(links)
.join("line")
.attr("stroke", "#666")
.attr("stroke-opacity", 0.6)
.attr("stroke-width", d => Math.sqrt(d.strength) * 2);
// Create nodes
const node = svg.append("g")
.selectAll("g")
.data(nodes)
.join("g")
.call(d3.drag()
.on("start", dragstarted)
.on("drag", dragged)
.on("end", dragended));
node.append("circle")
.attr("r", d => d.size)
.attr("fill", d => color(d.group))
.attr("stroke", "#e0e0e0")
.attr("stroke-width", 2);
node.append("text")
.text(d => d.id)
.attr("text-anchor", "middle")
.attr("dy", ".35em")
.attr("fill", "white")
.attr("font-size", d => Math.min(d.size / 3, 12))
.attr("font-weight", "bold");
// Add hover effects
node.on("mouseover", function(event, d) {
d3.select(this).select("circle")
.transition()
.duration(200)
.attr("r", d.size * 1.2)
.attr("filter", "drop-shadow(0 0 10px rgba(255, 107, 53, 0.8))");
link.attr("stroke-opacity", l =>
l.source.id === d.id || l.target.id === d.id ? 1 : 0.1
);
})
.on("mouseout", function(event, d) {
d3.select(this).select("circle")
.transition()
.duration(200)
.attr("r", d.size)
.attr("filter", "none");
link.attr("stroke-opacity", 0.6);
});
// Update positions
simulation.on("tick", () => {
link
.attr("x1", d => d.source.x)
.attr("y1", d => d.source.y)
.attr("x2", d => d.target.x)
.attr("y2", d => d.target.y);
node.attr("transform", d => `translate(${d.x},${d.y})`);
});
// Drag functions
function dragstarted(event, d) {
if (!event.active) simulation.alphaTarget(0.3).restart();
d.fx = d.x;
d.fy = d.y;
}
function dragged(event, d) {
d.fx = event.x;
d.fy = event.y;
}
function dragended(event, d) {
if (!event.active) simulation.alphaTarget(0);
d.fx = null;
d.fy = null;
}
}
// Migration Timeline
function createMigrationTimeline() {
const container = d3.select("#migration-timeline");
const width = container.node().getBoundingClientRect().width;
const height = 300;
container.selectAll("*").remove();
const svg = container.append("svg")
.attr("width", width)
.attr("height", height)
.attr("viewBox", [0, 0, width, height]);
const margin = {top: 40, right: 30, bottom: 50, left: 60};
const innerWidth = width - margin.left - margin.right;
const innerHeight = height - margin.top - margin.bottom;
const g = svg.append("g")
.attr("transform", `translate(${margin.left},${margin.top})`);
// Timeline data
const data = [
{phase: "Análisis", start: 0, duration: 5, color: "#FF9500"},
{phase: "Preparación", start: 3, duration: 7, color: "#FF6B35"},
{phase: "Migración", start: 8, duration: 4, color: "#F7435F"},
{phase: "Testing", start: 10, duration: 4, color: "#7B68EE"},
{phase: "Go Live", start: 12, duration: 2, color: "#4ECDC4"},
{phase: "Optimización", start: 14, duration: 6, color: "#95E1D3"}
];
// Scales
const xScale = d3.scaleLinear()
.domain([0, 20])
.range([0, innerWidth]);
const yScale = d3.scaleBand()
.domain(data.map(d => d.phase))
.range([0, innerHeight])
.padding(0.2);
// Create bars
g.selectAll(".bar")
.data(data)
.join("rect")
.attr("class", "bar")
.attr("x", d => xScale(d.start))
.attr("y", d => yScale(d.phase))
.attr("width", d => xScale(d.duration))
.attr("height", yScale.bandwidth())
.attr("fill", d => d.color)
.attr("rx", 4)
.style("opacity", 0)
.transition()
.duration(800)
.delay((d, i) => i * 100)
.style("opacity", 0.8);
// Add phase labels
g.selectAll(".label")
.data(data)
.join("text")
.attr("class", "label")
.attr("x", d => xScale(d.start) + xScale(d.duration) / 2)
.attr("y", d => yScale(d.phase) + yScale.bandwidth() / 2)
.attr("text-anchor", "middle")
.attr("dy", ".35em")
.attr("fill", "white")
.attr("font-size", "12px")
.attr("font-weight", "bold")
.text(d => d.phase);
// X axis
g.append("g")
.attr("transform", `translate(0,${innerHeight})`)
.call(d3.axisBottom(xScale).tickFormat(d => `Día ${d}`))
.style("color", "#999");
// Title
g.append("text")
.attr("x", innerWidth / 2)
.attr("y", -10)
.attr("text-anchor", "middle")
.attr("font-size", "14px")
.attr("font-weight", "bold")
.attr("fill", "#e0e0e0")
.text("Cronograma de Migración (20 días)");
}
// Hosting Comparison Matrix
function createHostingComparison() {
const container = d3.select("#hosting-comparison");
const width = container.node().getBoundingClientRect().width;
const height = 400;
container.selectAll("*").remove();
const svg = container.append("svg")
.attr("width", width)
.attr("height", height)
.attr("viewBox", [0, 0, width, height]);
const margin = {top: 50, right: 120, bottom: 60, left: 60};
const innerWidth = width - margin.left - margin.right;
const innerHeight = height - margin.top - margin.bottom;
const g = svg.append("g")
.attr("transform", `translate(${margin.left},${margin.top})`);
// Comparison data
const criteria = ["Costo", "Escalabilidad", "Performance", "Seguridad", "Soporte"];
const providers = [
{name: "AWS", values: [7, 10, 9, 10, 9], color: "#FF9500"},
{name: "On-Premise", values: [4, 3, 7, 6, 5], color: "#7B68EE"},
{name: "VPS Básico", values: [9, 4, 5, 5, 4], color: "#4ECDC4"}
];
// Scales
const xScale = d3.scaleBand()
.domain(criteria)
.range([0, innerWidth])
.padding(0.1);
const yScale = d3.scaleLinear()
.domain([0, 10])
.range([innerHeight, 0]);
// Create axes
g.append("g")
.attr("transform", `translate(0,${innerHeight})`)
.call(d3.axisBottom(xScale))
.style("color", "#999");
g.append("g")
.call(d3.axisLeft(yScale))
.style("color", "#999");
// Create bars for each provider
const barWidth = xScale.bandwidth() / providers.length;
providers.forEach((provider, i) => {
g.selectAll(`.bar-${i}`)
.data(provider.values)
.join("rect")
.attr("class", `bar-${i}`)
.attr("x", (d, j) => xScale(criteria[j]) + i * barWidth)
.attr("y", innerHeight)
.attr("width", barWidth - 2)
.attr("height", 0)
.attr("fill", provider.color)
.transition()
.duration(800)
.delay((d, j) => j * 100)
.attr("y", d => yScale(d))
.attr("height", d => innerHeight - yScale(d));
// Add value labels
g.selectAll(`.label-${i}`)
.data(provider.values)
.join("text")
.attr("class", `label-${i}`)
.attr("x", (d, j) => xScale(criteria[j]) + i * barWidth + barWidth / 2)
.attr("y", d => yScale(d) - 5)
.attr("text-anchor", "middle")
.attr("font-size", "11px")
.attr("fill", "#e0e0e0")
.style("opacity", 0)
.transition()
.duration(800)
.delay((d, j) => j * 100 + 400)
.style("opacity", 1)
.text(d => d);
});
// Legend
const legend = svg.append("g")
.attr("transform", `translate(${width - margin.right + 10}, ${margin.top})`);
providers.forEach((provider, i) => {
const legendItem = legend.append("g")
.attr("transform", `translate(0, ${i * 25})`);
legendItem.append("rect")
.attr("width", 18)
.attr("height", 18)
.attr("fill", provider.color);
legendItem.append("text")
.attr("x", 24)
.attr("y", 9)
.attr("dy", ".35em")
.attr("font-size", "12px")
.attr("fill", "#e0e0e0")
.text(provider.name);
});
// Y axis label
g.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 0 - margin.left)
.attr("x", 0 - (innerHeight / 2))
.attr("dy", "1em")
.style("text-anchor", "middle")
.style("font-size", "12px")
.style("fill", "#999")
.text("Puntuación (1-10)");
}
// Initialize visualizations when scrolled into view
const observerOptions = {
threshold: 0.1,
rootMargin: "0px 0px -100px 0px"
};
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const id = entry.target.id;
switch(id) {
case 'aws-ecosystem':
createAWSEcosystem();
observer.unobserve(entry.target);
break;
case 'migration-timeline':
createMigrationTimeline();
observer.unobserve(entry.target);
break;
case 'hosting-comparison':
createHostingComparison();
observer.unobserve(entry.target);
break;
}
}
});
}, observerOptions);
// Observe visualization containers
document.addEventListener('DOMContentLoaded', function() {
document.querySelectorAll('.chart-container').forEach(container => {
observer.observe(container);
});
});
// Handle window resize
let resizeTimer;
window.addEventListener('resize', () => {
clearTimeout(resizeTimer);
resizeTimer = setTimeout(() => {
const ecosystem = document.querySelector('#aws-ecosystem');
if (ecosystem && ecosystem.getBoundingClientRect().top < window.innerHeight) {
createAWSEcosystem();
}
const timeline = document.querySelector('#migration-timeline');
if (timeline && timeline.getBoundingClientRect().top < window.innerHeight) {
createMigrationTimeline();
}
const comparison = document.querySelector('#hosting-comparison');
if (comparison && comparison.getBoundingClientRect().top < window.innerHeight) {
createHostingComparison();
}
}, 250);
});
</script>
</body>
</html>