optimize for SEO

D David Veksler · 1 year ago 4dd2ba0e149e05ec3803a038efe5900e214ee483
Parent: c5c4198c1

1 file changed +132 −46

Diff

diff --git a/lifestyle-calculator.html b/lifestyle-calculator.html
index 4e97e3d..0ab4a12 100644
--- a/lifestyle-calculator.html
+++ b/lifestyle-calculator.html
@@ -12,6 +12,7 @@
     <meta content="https://cheatsheets.davidveksler.com/lifestyle-calculator.html" property="og:url"/>
     <meta content="Lifestyle Calculator: What Your Family's Income Really Buys" property="og:title"/>
     <meta content="Explore how different family income levels translate to real lifestyle choices, with a basic Cost of Living Adjustment. See what your household can afford from $20K to $25M+." property="og:description"/>
+    <meta content="images/lifestyle-calculator.png" property="og:image"/>
     <meta content="Interactive lifestyle calculator showing income to lifestyle progression " property="og:image:alt"/>
     <meta content="1200" property="og:image:width"/>
     <meta content="630" property="og:image:height"/>
@@ -20,11 +21,32 @@
     <meta content="https://cheatsheets.davidveksler.com/lifestyle-calculator.html" name="twitter:url"/>
     <meta content="Lifestyle Calculator: What Your Family's Income Really Buys" name="twitter:title"/>
     <meta content="Explore how different family income levels translate to real lifestyle choices, with a basic Cost of Living Adjustment. See what your household can afford from $20K to $25M+." name="twitter:description"/>
-    <link crossorigin="anonymous" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" rel="stylesheet"/>
+    <meta content="images/lifestyle-calculator.png" name="twitter:image"/>
+    
+    <!-- SEO: JSON-LD Structured Data -->
+    <script type="application/ld+json">
+    {
+      "@context": "https://schema.org",
+      "@type": "WebApplication",
+      "name": "Lifestyle Calculator: What Your Family's Income Really Buys",
+      "description": "An interactive tool to explore how family income levels from $20K to $25M+ translate to real-world lifestyle choices in housing, dining, travel, and more, with cost of living adjustments.",
+      "applicationCategory": "FinanceApplication",
+      "operatingSystem": "All",
+      "browserRequirements": "Requires a modern web browser with JavaScript enabled.",
+      "url": "https://cheatsheets.davidveksler.com/lifestyle-calculator.html",
+      "creator": {
+        "@type": "Person",
+        "name": "David Veksler"
+      },
+      "keywords": "lifestyle calculator, income lifestyle, family budget, what can I afford, salary lifestyle, finance, cost of living, financial planning"
+    }
+    </script>
+
+    <link crossorigin="anonymous" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH"/>
     <link href="https://cdn.jsdelivr.net/npm/[email protected]/font/bootstrap-icons.min.css" rel="stylesheet"/>
     <link href="https://fonts.googleapis.com" rel="preconnect"/>
     <link crossorigin="" href="https://fonts.gstatic.com" rel="preconnect"/>
-    <link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&amp;family=Roboto+Slab:wght@700&amp;display=swap" rel="stylesheet"/>
+    <link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&family=Roboto+Slab:wght@700&display=swap" rel="stylesheet"/>
     <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
     <style>
         :root {
@@ -253,7 +275,7 @@
     <div id="background-layer-2"></div>
 </div>
 
-<div class="container">
+<main class="container">
     <div class="main-container">
         <div class="text-center">
             <h1 class="page-title">💰 Lifestyle Calculator</h1>
@@ -267,7 +289,7 @@
                     <div class="row">
                         <div class="col-md-6 mb-3 mb-md-0">
                             <label class="form-label" for="colaSelector">Cost of Living Adjustment (COLA):</label>
-                            <select class="form-select form-select-sm" id="colaSelector"><!-- Options populated by JS --></select>
+                            <select class="form-select form-select-sm" id="colaSelector"></select>
                         </div>
                         <div class="col-md-6">
                             <label class="form-label" for="familySizeSelector">Household / Life Stage:</label>
@@ -297,21 +319,32 @@
 
         <div class="row">
             <div class="col-lg-6">
-                <div class="lifestyle-category dining fade-in"><div class="category-title"><i class="bi bi-egg-fried category-icon"></i> Dining &amp; Food</div><div id="dining-content"></div></div>
-                <div class="lifestyle-category travel fade-in"><div class="category-title"><i class="bi bi-airplane category-icon"></i> Travel &amp; Vacations</div><div id="travel-content"></div></div>
-                <div class="lifestyle-category housing fade-in"><div class="category-title"><i class="bi bi-house-door category-icon"></i> Housing &amp; Living</div><div id="housing-content"></div></div>
+                <div class="lifestyle-category dining fade-in"><div class="category-title"><i class="bi bi-egg-fried category-icon"></i> Dining & Food</div><div id="dining-content"></div></div>
+                <div class="lifestyle-category travel fade-in"><div class="category-title"><i class="bi bi-airplane category-icon"></i> Travel & Vacations</div><div id="travel-content"></div></div>
+                <div class="lifestyle-category housing fade-in"><div class="category-title"><i class="bi bi-house-door category-icon"></i> Housing & Living</div><div id="housing-content"></div></div>
                 <div class="lifestyle-category transportation fade-in"><div class="category-title"><i class="bi bi-car-front-fill category-icon"></i> Transportation</div><div id="transportation-content"></div></div>
             </div>
             <div class="col-lg-6">
-                <div class="lifestyle-category entertainment fade-in"><div class="category-title"><i class="bi bi-dice-5-fill category-icon"></i> Entertainment &amp; Hobbies</div><div id="entertainment-content"></div></div>
-                <div class="lifestyle-category education fade-in"><div class="category-title"><i class="bi bi-book-half category-icon"></i> Education &amp; Growth</div><div id="education-content"></div></div>
+                <div class="lifestyle-category entertainment fade-in"><div class="category-title"><i class="bi bi-dice-5-fill category-icon"></i> Entertainment & Hobbies</div><div id="entertainment-content"></div></div>
+                <div class="lifestyle-category education fade-in"><div class="category-title"><i class="bi bi-book-half category-icon"></i> Education & Growth</div><div id="education-content"></div></div>
                 <div class="lifestyle-category health-wellness fade-in"><div class="category-title"><i class="bi bi-heart-pulse-fill category-icon"></i> Health & Wellness</div><div id="health-wellness-content"></div></div>
                 <div class="lifestyle-category services fade-in"><div class="category-title"><i class="bi bi-person-check-fill category-icon"></i> Personal Services</div><div id="services-content"></div></div>
-                <div class="lifestyle-category financial-planning fade-in"><div class="category-title"><i class="bi bi-piggy-bank category-icon"></i> Financial Planning &amp; Investments</div><div id="financial-services-content"></div></div>
+                <div class="lifestyle-category financial-planning fade-in"><div class="category-title"><i class="bi bi-piggy-bank category-icon"></i> Financial Planning & Investments</div><div id="financial-services-content"></div></div>
             </div>
         </div>
     </div>
-</div>
+</main>
+
+<footer class="container text-center py-3">
+    <div>
+        <a class="mx-2 link-secondary" href="https://www.linkedin.com/in/davidveksler/" target="_blank" title="David Veksler on LinkedIn">
+            <i class="bi bi-linkedin"></i> LinkedIn
+        </a>
+        <a class="mx-2 link-secondary" href="https://cheatsheets.davidveksler.com/" title="Browse All Cheatsheets">
+            <i class="bi bi-collection"></i> All Cheatsheets
+        </a>
+    </div>
+</footer>
 
 <div id="milestone-popup">
     <span id="milestone-emoji"></span>
@@ -375,48 +408,101 @@ function updateBudgetChart(bracketIndex) {
 
     const labels = Object.keys(bracketData.budgetAllocation);
     const data = Object.values(bracketData.budgetAllocation);
+    
+    // A more sophisticated, financial-themed color palette
+    const colorPalette = [
+        '#2d4059', // Deep Blue
+        '#ea5455', // Muted Red
+        '#f07b3f', // Orange
+        '#ffd460', // Yellow
+        '#7e9a9a', // Teal-Gray
+        '#4a6c6f', // Darker Teal
+        '#99a8b2', // Light Slate
+        '#596e79'  // Medium Slate
+    ];
 
-    if (budgetChart) {
-        budgetChart.data.labels = labels;
-        budgetChart.data.datasets[0].data = data;
-        budgetChart.update('none'); // Update without animation
-    } else {
-        const ctx = document.getElementById('budgetChart').getContext('2d');
-        budgetChart = new Chart(ctx, {
-            type: 'doughnut',
-            data: {
-                labels: labels,
-                datasets: [{
-                    label: 'Budget Allocation',
-                    data: data,
-                    backgroundColor: ['#0d6efd', '#198754', '#ffc107', '#fd7e14', '#6f42c1', '#d63384', '#20c997', '#6c757d'],
-                    borderColor: '#fff',
-                    borderWidth: 2,
-                    hoverOffset: 4
-                }]
+    const chartConfig = {
+        type: 'doughnut',
+        data: {
+            labels: labels,
+            datasets: [{
+                label: 'Budget Allocation',
+                data: data,
+                backgroundColor: colorPalette,
+                borderColor: '#ffffff',
+                borderWidth: 3,
+                hoverBorderColor: '#f8f9fa',
+                hoverBorderWidth: 1,
+                hoverOffset: 8
+            }]
+        },
+        options: {
+            responsive: true,
+            maintainAspectRatio: false,
+            cutout: '70%', // Makes the doughnut a bit thinner and more modern
+            animation: {
+                animateScale: true,
+                animateRotate: true
             },
-            options: {
-                responsive: true,
-                maintainAspectRatio: false,
-                plugins: {
-                    legend: { display: false },
-                    tooltip: {
-                        callbacks: {
-                            label: function(context) {
-                                let label = context.label || '';
-                                if (label) {
-                                    label += ': ';
-                                }
-                                if (context.parsed !== null) {
-                                    label += context.parsed + '%';
-                                }
-                                return label;
+            plugins: {
+                legend: {
+                    display: true,
+                    position: 'right', // Display labels in a legend
+                    align: 'center',
+                    labels: {
+                        boxWidth: 12,
+                        padding: 15,
+                        font: {
+                            size: 11,
+                            family: "'Inter', sans-serif"
+                        },
+                        color: '#495057'
+                    }
+                },
+                tooltip: {
+                    enabled: true,
+                    backgroundColor: 'rgba(0, 0, 0, 0.8)',
+                    titleFont: {
+                        size: 14,
+                        weight: 'bold'
+                    },
+                    bodyFont: {
+                        size: 12
+                    },
+                    padding: 12,
+                    cornerRadius: 8,
+                    callbacks: {
+                        label: function(context) {
+                            let label = context.label || '';
+                            if (label) {
+                                label += ': ';
+                            }
+                            if (context.parsed !== null) {
+                                label += context.parsed + '%';
                             }
+                            return label;
                         }
                     }
                 }
+            },
+            layout: {
+                padding: {
+                    left: 0,
+                    right: 10 // Add padding to ensure legend labels are not cut off
+                }
             }
-        });
+        }
+    };
+
+    if (budgetChart) {
+        budgetChart.data.labels = labels;
+        budgetChart.data.datasets[0].data = data;
+        // Re-apply config on update to ensure settings persist
+        budgetChart.options = chartConfig.options; 
+        budgetChart.update(); // Use default animation on update
+    } else {
+        const ctx = document.getElementById('budgetChart').getContext('2d');
+        budgetChart = new Chart(ctx, chartConfig);
     }
 }