Home / Blog / Zero-Downtime Site Migrations. URL Mapping
AI SEO 1 July 2025 3 min read

Zero-Downtime Site Migrations. URL Mapping

Migrating an enterprise website with 50,000 URLs is the most high-risk operation a technical team can execute. Historically, even the most meticulous.

LB
Lee Beirne
leebeirne.com

Migrating an enterprise website with 50,000 URLs is the most high-risk operation a technical team can execute. Historically, even the most meticulous migrations result in a 15% to 20% drop in organic traffic during the transition period.

The root cause of this failure is almost always human error. SEO agencies attempt to map thousands of 301 redirects using massive Excel spreadsheets. They rely on basic VLOOKUP functions, fuzzy string matching, or junior staff manually verifying slugs. It is slow, highly inaccurate, and inevitably leads to broken redirect chains, unmapped orphans, and catastrophic PageRank loss.

To safely migrate an enterprise architecture, you must eliminate the spreadsheet entirely. You execute this by deploying an autonomous URL-Mapping Agent.

The Problem with String Matching

A zero-downtime site migration is the process of moving a website from one platform, domain, or architecture to another without losing search rankings, traffic, or user access. The most critical component is URL mapping, which ensures every old URL redirects correctly to its new equivalent. For enterprise sites with 50,000+ URLs, this requires automated agents that can match old URLs to new ones based on content similarity, not just text patterns. Failed migrations can result in 30-80% traffic loss that takes months to recover.

Legacy redirect strategies fail because they map URLs based on text strings rather than semantic intent. If your legacy URL is /category/mens-shoes-red and your staging site URL changes to /footwear/men/red-sneakers, a standard Excel script will fail to map them.

Google does not rank strings; it ranks semantic entities. Therefore, your redirect map must be built mathematically, based on the underlying meaning of the pages. This is where agentic pipelines become necessary.

Step 1: Vector Ingestion

Instead of exporting simple lists of URLs, I deploy a Python-based ingestion agent. The agent crawls both the legacy live site and the protected staging environment. However, it does not just record the slug.

It parses the


</p> <p>tag, the primary H1, and the core paragraph content of every single URL. It then streams this raw HTML through an embedding model, converting the semantic meaning of all 50,000 pages into high-dimensional vector space.</p> <h2 id="step-2-semantic-relevance-mapping">Step 2: Semantic Relevance Mapping</h2> <p>Once the data is embedded mathematically, the agent executes a cosine similarity search. It compares the vector space of the old site to the new site.</p> <p>The agent does not care that the URL slug changed entirely. It understands that the semantic relationship between the legacy shoe category and the new footwear taxonomy is identical. It pairs them mathematically, achieving a mapping accuracy that humans cannot replicate at scale.</p> <h2 id="step-3-autonomous-configuration-and-deployment">Step 3: Autonomous Configuration and Deployment</h2> <p>The agent does not output an Excel file for a developer to manually convert. It is instructed to autonomously output a perfectly formatted Nginx <br> <br> <br> .conf</p> <p>file (or Apache <br> <br> <br> .htaccess</p> <p>ruleset), ensuring the syntax is flawless.</p> <p>However, no agent should push critical configuration to production without oversight. Any mapped URL pairing that falls below a 95% semantic confidence threshold is instantly routed to a <a href="/blog/remote-control-seo-managing-agents-via-telegram-hermes">Telegram exception queue</a>.</p> <p>The technical lead receives a ping on their phone: "Confidence Score 82% - Map Legacy URL X to Stageing URL Y? [Approve] [Reject]". The human intervenes only for edge cases, while the machine handles the other 49,900 perfect matches autonomously.</p> <h2 id="zero-downtime-zero-traffic-loss">Zero Downtime, Zero Traffic Loss</h2> <p>By shifting from manual spreadsheet mapping to vector-based agentic architecture, you turn a highly dangerous, three-week manual task into a two-hour mathematical execution.</p> <p>If you are preparing for a massive site migration and cannot afford to lose your organic visibility, <a href="/contact">let\'s talk</a>.</p></div> <div class="bg-[#0F172A] p-8 my-8 border-l-4 border-[#10B981]"><h3 class="text-white font-bold text-lg mb-2" style="font-family:'Space Grotesk',sans-serif">Get SEO insights in your inbox</h3><p class="text-white/60 text-sm mb-4" style="font-family:'Inter',sans-serif">Weekly insights on AI SEO, LLMO, technical SEO, and what actually moves rankings. No fluff.</p><form id="newsletter-inline-en" data-button="Subscribe" class="space-y-3"><div class="grid grid-cols-2 gap-3"><input type="text" name="firstName" required aria-label="First name" placeholder="First name" class="px-4 py-2.5 bg-white/10 border border-white/20 text-white placeholder:text-white/40 text-sm focus:outline-none focus:border-[#10B981]" style="font-family:'Inter',sans-serif"><input type="text" name="lastName" aria-label="Last name (optional)" placeholder="Last name (optional)" class="px-4 py-2.5 bg-white/10 border border-white/20 text-white placeholder:text-white/40 text-sm focus:outline-none focus:border-[#10B981]" style="font-family:'Inter',sans-serif"></div><input type="email" name="email" required aria-label="your@email.com" placeholder="your@email.com" class="w-full px-4 py-2.5 bg-white/10 border border-white/20 text-white placeholder:text-white/40 text-sm focus:outline-none focus:border-[#10B981]" style="font-family:'Inter',sans-serif"><select name="language" aria-label="Language" class="w-full px-4 py-2.5 bg-[#1E3A8A] border border-white/20 text-white text-sm focus:outline-none focus:border-[#10B981]" style="font-family:'Inter',sans-serif"><option value="en" class="bg-[#1E3A8A] text-white">English</option><option value="es" class="bg-[#1E3A8A] text-white">Español</option><option value="both" class="bg-[#1E3A8A] text-white">Both</option></select><button type="submit" class="w-full px-6 py-2.5 bg-[#10B981] text-white font-semibold text-sm hover:bg-[#059669] transition-colors" style="font-family:'Inter',sans-serif">Subscribe</button></form><div id="newsletter-inline-en-success" role="status" class="hidden mt-4 p-4 bg-[#10B981]/20 border border-[#10B981]/30 text-[#10B981] text-sm" style="font-family:'Inter',sans-serif"><p class="font-semibold">Thanks for subscribing! You'll receive your first email soon.</p></div><div id="newsletter-inline-en-error" role="alert" class="hidden mt-4 p-4 bg-red-500/20 border border-red-500/30 text-red-300 text-sm" style="font-family:'Inter',sans-serif"><p class="font-semibold">Something went wrong. Please try again or email me directly.</p></div><p class="text-white/30 text-xs mt-3" style="font-family:'Inter',sans-serif">No spam. Unsubscribe anytime.</p></div><script type="module">document.addEventListener("DOMContentLoaded",function(){document.querySelectorAll('form[id^="newsletter-"]').forEach(function(e){e.addEventListener("submit",function(d){d.preventDefault();var l=e.querySelector("[name=firstName]").value,u=e.querySelector("[name=lastName]").value||"",i=e.querySelector("[name=email]").value,m=e.querySelector("[name=language]").value,o=e.id;document.getElementById(o+"-success");var n=e.querySelector("button[type=submit]");n.disabled=!0,n.textContent="...";var a="api_key=eo_85945b5e4f7c9c175eb50863bf702677cfb28f5faf557c2614de487e4f1cb09e";a+="&email_address="+encodeURIComponent(i),a+="&fields[FirstName]="+encodeURIComponent(l),a+="&fields[LastName]="+encodeURIComponent(u),a+="&fields[Language]="+encodeURIComponent(m),a+="&status=SUBSCRIBED";var t=new XMLHttpRequest;t.open("POST","https://emailoctopus.com/api/1.5/lists/4e0163e4-8c3e-11f1-b66f-8b4d76a765c4/contacts",!0),t.setRequestHeader("Content-Type","application/x-www-form-urlencoded");var r=function(c){e.style.display="none";var s=document.getElementById(o+(c?"-success":"-error"));s&&(s.classList.remove("hidden"),s.style.display="block"),c||(e.style.display=""),n.disabled=!1,n.textContent=e.getAttribute("data-button")||"Subscribe"};t.onreadystatechange=function(){t.readyState===4&&r(t.status>=200&&t.status<300)},t.onerror=function(){r(!1)},t.send(a)})})});</script> </div> </div> <div class="lg:col-span-1 space-y-6"> <div class="bg-[#0F172A] p-6"> <div class="w-12 h-12 bg-[#1E3A8A] flex items-center justify-center mb-4"> <span class="text-white font-bold text-lg" style="font-family:'Space Grotesk',sans-serif">LB</span> </div> <div class="text-white font-bold text-lg mb-1" style="font-family:'Space Grotesk',sans-serif">Lee Beirne</div> <div class="text-white/50 text-xs mb-4" style="font-family:'Inter',sans-serif">AI SEO Consultant · 30 Years Experience</div> <p class="text-white/60 text-sm leading-relaxed mb-5" style="font-family:'Inter',sans-serif">Blending battle-tested SEO expertise with cutting-edge AI to deliver measurable growth.</p> <a href="/contact/" class="btn-cta w-full justify-center text-sm py-2.5">Work With Lee <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="5" y1="12" x2="19" y2="12"></line><polyline points="12 5 19 12 12 19"></polyline></svg></a> </div> <div class="bg-white border border-gray-100 p-6"> <div class="text-xs font-semibold uppercase tracking-widest text-[#C2410C] mb-3" style="font-family:'Inter',sans-serif">Topic Cluster</div> <div class="text-gray-900 font-bold text-sm mb-4" style="font-family:'Space Grotesk',sans-serif">Technical SEO</div> <a href="/blog/?cluster=technical-seo" class="flex items-center gap-2 text-[#1E3A8A] text-sm font-semibold mb-3 hover:text-[#C2410C] transition-colors" style="font-family:'Space Grotesk',sans-serif"> <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"></path><polyline points="15 3 21 3 21 9"></polyline><line x1="10" y1="14" x2="21" y2="3"></line></svg> View Technical SEO Posts </a> <a href="/services/technical-seo" class="flex items-center gap-2 text-[#1E3A8A] text-sm font-semibold mb-4 hover:text-[#C2410C] transition-colors" style="font-family:'Space Grotesk',sans-serif"> <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"></path><polyline points="15 3 21 3 21 9"></polyline><line x1="10" y1="14" x2="21" y2="3"></line></svg> View Technical SEO Services </a> <div> <div class="text-xs font-semibold text-gray-500 uppercase tracking-widest mb-3">Related Posts</div> <div class="space-y-3"> <a href="/blog/ai-agents-are-transforming-technical-seo" class="block text-[#1E3A8A] text-sm hover:text-[#C2410C] transition-colors" style="font-family:'Inter',sans-serif"> AI Agents Are Transforming Technical SEO </a><a href="/blog/automate-server-log-file-analysis-local-llms" class="block text-[#1E3A8A] text-sm hover:text-[#C2410C] transition-colors" style="font-family:'Inter',sans-serif"> Automate Log File Analysis with Local LLMs </a><a href="/blog/self-healing-websites-future-agentic-seo-architecture" class="block text-[#1E3A8A] text-sm hover:text-[#C2410C] transition-colors" style="font-family:'Inter',sans-serif"> Self-Healing Websites. Agentic SEO Architecture </a><a href="/blog/stop-ai-hallucinations-seo-knowledge-graph-deepseek-v4" class="block text-[#1E3A8A] text-sm hover:text-[#C2410C] transition-colors" style="font-family:'Inter',sans-serif"> Stop AI Hallucinations with Knowledge Graphs </a> </div> </div> </div> <a href="/blog/" class="flex items-center gap-2 text-[#1E3A8A] text-sm font-semibold hover:gap-3 transition-all" style="font-family:'Space Grotesk',sans-serif"> <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="19" y1="12" x2="5" y2="12"></line><polyline points="12 19 5 12 12 5"></polyline></svg> Back to all posts </a> </div> </div> </div> </section> <button id="return-to-top" class="fixed bottom-8 right-8 w-12 h-12 bg-[#1E3A8A] text-white flex items-center justify-center shadow-lg hover:bg-[#C2410C] transition-all duration-300 opacity-0 pointer-events-none z-50" aria-label="Return to top"> <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="18 15 12 9 6 15"></polyline></svg> </button> </main> <!-- Footer --> <footer class="bg-[#0F172A] text-white"> <div class="container py-16"> <div class="grid grid-cols-1 md:grid-cols-3 gap-12 mb-12"> <div> <div class="flex items-center gap-3 mb-4"> <div class="w-9 h-9 rounded-lg bg-[#1E3A8A] flex items-center justify-center"> <span style="font-family:'Space Grotesk','Space Grotesk Fallback',sans-serif;font-weight:700;font-size:14px;color:white">LB</span> </div> <span style="font-family:'Space Grotesk','Space Grotesk Fallback',sans-serif;font-weight:700;font-size:18px;letter-spacing:-0.02em">Lee Beirne</span> </div> <p class="text-white/60 text-sm leading-relaxed max-w-xs" style="font-family:'Inter','Inter Fallback',sans-serif"> AI SEO Consultant with nearly 30 years of experience. Blending battle-tested SEO expertise with cutting-edge AI to deliver measurable growth. </p> <div class="flex items-center gap-3 mt-6"> <a href="https://www.linkedin.com/in/leebeirne/" target="_blank" rel="noopener noreferrer" class="w-9 h-9 rounded-lg bg-white/10 flex items-center justify-center hover:bg-[#1E3A8A] transition-colors duration-200" aria-label="LinkedIn"> <svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor"><path d="M20.447 20.452h-3.554v-5.569c0-1.328-.027-3.037-1.852-3.037-1.853 0-2.136 1.445-2.136 2.939v5.667H9.351V9h3.414v1.561h.046c.477-.9 1.637-1.85 3.37-1.85 3.601 0 4.267 2.37 4.267 5.455v6.286zM5.337 7.433c-1.144 0-2.063-.926-2.063-2.065 0-1.138.92-2.063 2.063-2.063 1.14 0 2.064.925 2.064 2.063 0 1.139-.925 2.065-2.064 2.065zm1.782 13.019H3.555V9h3.564v11.452zM22.225 0H1.771C.792 0 0 .774 0 1.729v20.542C0 23.227.792 24 1.771 24h20.451C23.2 24 24 23.227 24 22.271V1.729C24 .774 23.2 0 22.222 0h.003z"></path></svg> </a> <a href="mailto:hi@leebeirne.com" class="w-9 h-9 rounded-lg bg-white/10 flex items-center justify-center hover:bg-[#EA580C] transition-colors duration-200" aria-label="Email"> <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="2" y="4" width="20" height="16" rx="2"></rect><path d="m22 7-8.97 5.7a1.94 1.94 0 0 1-2.06 0L2 7"></path></svg> </a> </div> </div> <div> <div class="text-sm font-semibold text-white/60 uppercase tracking-widest mb-5" style="font-family:'Space Grotesk','Space Grotesk Fallback',sans-serif">Navigation</div> <nav class="flex flex-col gap-3"> <a href="/" class="text-white/60 hover:text-white text-sm transition-colors duration-200" style="font-family:'Inter','Inter Fallback',sans-serif">Home</a><a href="/about/" class="text-white/60 hover:text-white text-sm transition-colors duration-200" style="font-family:'Inter','Inter Fallback',sans-serif">About</a><a href="/services/" class="text-white/60 hover:text-white text-sm transition-colors duration-200" style="font-family:'Inter','Inter Fallback',sans-serif">Services</a><a href="/blog/" class="text-white/60 hover:text-white text-sm transition-colors duration-200" style="font-family:'Inter','Inter Fallback',sans-serif">Blog</a><a href="/seo-pricing-calculator/" class="text-white/60 hover:text-white text-sm transition-colors duration-200" style="font-family:'Inter','Inter Fallback',sans-serif">SEO Pricing</a><a href="/contact/" class="text-white/60 hover:text-white text-sm transition-colors duration-200" style="font-family:'Inter','Inter Fallback',sans-serif">Contact</a> </nav> </div> <div> <div class="text-sm font-semibold text-white/60 uppercase tracking-widest mb-5" style="font-family:'Space Grotesk','Space Grotesk Fallback',sans-serif">Services</div> <nav class="flex flex-col gap-3"> <a href="/services/content-marketing/" class="text-white/60 hover:text-white text-sm transition-colors" style="font-family:'Inter','Inter Fallback',sans-serif">Content Marketing</a><a href="/services/llmo/" class="text-white/60 hover:text-white text-sm transition-colors" style="font-family:'Inter','Inter Fallback',sans-serif">LLMO</a><a href="/services/link-building/" class="text-white/60 hover:text-white text-sm transition-colors" style="font-family:'Inter','Inter Fallback',sans-serif">Link Building</a><a href="/services/igaming-seo/" class="text-white/60 hover:text-white text-sm transition-colors" style="font-family:'Inter','Inter Fallback',sans-serif">iGaming SEO</a><a href="/services/cro/" class="text-white/60 hover:text-white text-sm transition-colors" style="font-family:'Inter','Inter Fallback',sans-serif">CRO</a><a href="/services/competitor-analysis/" class="text-white/60 hover:text-white text-sm transition-colors" style="font-family:'Inter','Inter Fallback',sans-serif">Competitor Analysis</a><a href="/services/analytics/" class="text-white/60 hover:text-white text-sm transition-colors" style="font-family:'Inter','Inter Fallback',sans-serif">Analytics</a><a href="/services/fintech-seo/" class="text-white/60 hover:text-white text-sm transition-colors" style="font-family:'Inter','Inter Fallback',sans-serif">Fintech SEO</a><a href="/services/technical-seo/" class="text-white/60 hover:text-white text-sm transition-colors" style="font-family:'Inter','Inter Fallback',sans-serif">Technical SEO</a><a href="/services/local-seo/" class="text-white/60 hover:text-white text-sm transition-colors" style="font-family:'Inter','Inter Fallback',sans-serif">Local SEO</a> </nav> </div> </div> <div class="border-t border-white/10 pt-8 flex flex-col md:flex-row items-center justify-between gap-4"> <div class="flex items-center gap-4"> <p class="text-white/60 text-sm" style="font-family:'Inter','Inter Fallback',sans-serif">© 2026 Lee Beirne. All rights reserved.</p> <span class="text-white/30">|</span> <a href="/privacy-policy" class="text-white/70 hover:text-white text-xs transition-colors" style="font-family:'Inter','Inter Fallback',sans-serif">Privacy</a> <a href="/terms-of-service" class="text-white/70 hover:text-white text-xs transition-colors" style="font-family:'Inter','Inter Fallback',sans-serif">Terms</a> </div> <p class="text-white/50 text-xs" style="font-family:'Inter','Inter Fallback',sans-serif">AI SEO Consultant · Spain, UK & Global</p> </div> </div> </footer> <!-- Navigation scroll script --> <script> const header = document.getElementById('site-header'); const logoText = document.getElementById('logo-text'); const githubBtn = document.getElementById('github-btn'); const navLinks = document.querySelectorAll('.nav-link'); const menuToggle = document.getElementById('menu-toggle'); const mobileMenu = document.getElementById('mobile-menu'); const mobilePanel = document.getElementById('mobile-panel'); const mobileOverlay = document.getElementById('mobile-overlay'); const mobileNavLinks = document.querySelectorAll('.mobile-nav-link'); let mobileOpen = false; function toggleMobile() { mobileOpen = !mobileOpen; if (mobileOpen) { mobileMenu.classList.remove('opacity-0', 'pointer-events-none'); mobileMenu.classList.add('opacity-100', 'pointer-events-auto'); mobilePanel.classList.remove('translate-x-full'); mobilePanel.classList.add('translate-x-0'); } else { mobileMenu.classList.add('opacity-0', 'pointer-events-none'); mobileMenu.classList.remove('opacity-100', 'pointer-events-auto'); mobilePanel.classList.add('translate-x-full'); mobilePanel.classList.remove('translate-x-0'); } } menuToggle?.addEventListener('click', toggleMobile); mobileOverlay?.addEventListener('click', toggleMobile); mobileNavLinks.forEach(link => { link.addEventListener('click', () => { if (mobileOpen) toggleMobile(); }); }); function updateNavState() { const scrolled = window.scrollY > 40; const langToggleBtn = document.getElementById('lang-toggle-btn'); if (scrolled) { header.classList.add('bg-white/95', 'backdrop-blur-xl', 'shadow-sm', 'border-b', 'border-gray-100'); header.classList.remove('bg-transparent'); logoText.classList.remove('text-white'); logoText.classList.add('text-gray-900'); navLinks.forEach(link => { link.classList.remove('text-white/85'); link.classList.add('text-gray-700'); }); if (githubBtn) { githubBtn.classList.remove('border-white/30', 'text-white/85', 'bg-white/10'); githubBtn.classList.add('border-gray-200', 'text-gray-700', 'bg-white'); } if (langToggleBtn) { langToggleBtn.classList.remove('border-white/30', 'text-white/85', 'bg-white/10'); langToggleBtn.classList.add('border-gray-200', 'text-gray-700', 'bg-white'); } if (menuToggle) { menuToggle.classList.remove('text-white', 'hover:bg-white/10'); menuToggle.classList.add('text-gray-900', 'hover:bg-gray-100'); } } else { header.classList.remove('bg-white/95', 'backdrop-blur-xl', 'shadow-sm', 'border-b', 'border-gray-100'); header.classList.add('bg-transparent'); logoText.classList.add('text-white'); logoText.classList.remove('text-gray-900'); navLinks.forEach(link => { link.classList.add('text-white/85'); link.classList.remove('text-gray-700'); }); if (githubBtn) { githubBtn.classList.add('border-white/30', 'text-white/85', 'bg-white/10'); githubBtn.classList.remove('border-gray-200', 'text-gray-700', 'bg-white'); } if (langToggleBtn) { langToggleBtn.classList.add('border-white/30', 'text-white/85', 'bg-white/10'); langToggleBtn.classList.remove('border-gray-200', 'text-gray-700', 'bg-white'); } if (menuToggle) { menuToggle.classList.add('text-white', 'hover:bg-white/10'); menuToggle.classList.remove('text-gray-900', 'hover:bg-gray-100'); } } } window.addEventListener('scroll', updateNavState, { passive: true }); updateNavState(); // Language switcher var langToggleBtn = document.getElementById('lang-toggle-btn'); var langMenu = document.getElementById('lang-menu'); if (langToggleBtn) { langToggleBtn.addEventListener('click', function(e) { e.stopPropagation(); langMenu.classList.toggle('hidden'); }); } // Close lang menu when clicking outside document.addEventListener('click', function(e) { var switcher = document.getElementById('lang-switcher'); if (switcher && !switcher.contains(e.target)) { langMenu.classList.add('hidden'); } }); </script> <a href="https://wa.me/34623613156?text=Hi%2C%20I%20found%20you%20through%20your%20website%20and%20would%20like%20to%20discuss%20how%20you%20can%20help%20me." class="whatsapp-float" target="_blank" rel="noopener noreferrer" aria-label="Chat with me on WhatsApp" data-astro-cid-iehx2mtc> <svg viewBox="0 0 32 32" aria-hidden="true" width="24" height="24" data-astro-cid-iehx2mtc> <path d="M16.004 00h-.008C7.174 0 0 7.176 0 16c0 2.824.736 5.588 2.132 8.024L0 32l8.2-2.152A15.94 15.94 0 0016 32h.008C24.826 32 32 24.824 32 16S24.826 0 16.004 0zm0 29.2h-.008a13.16 13.16 0 01-6.716-1.84l-.48-.288-5.016 1.316 1.34-4.888-.312-.504A13.14 13.14 0 012.8 16c0-7.272 5.928-13.2 13.2-13.2h.008c7.272 0 13.2 5.928 13.2 13.2 0 7.272-5.928 13.2-13.2 13.2zm7.26-9.864c-.396-.2-2.34-1.156-2.704-1.288-.364-.132-.628-.2-.892.2-.264.396-1.024 1.288-1.256 1.552-.232.264-.464.296-.86.1-.396-.2-1.672-.616-3.184-1.968-1.176-1.048-1.972-2.336-2.204-2.732-.232-.396-.024-.612.176-.812.18-.18.396-.464.596-.7.2-.232.264-.396.396-.66.132-.264.068-.496-.032-.7-.1-.2-.892-2.16-1.224-2.952-.32-.776-.648-.672-.892-.688-.232-.016-.496-.02-.76-.02-.264 0-.7.1-1.064.496-.364.396-1.392 1.36-1.392 3.304 0 1.944 1.424 3.816 1.624 4.08.2.264 2.804 4.28 6.8 6 .948.42 1.688.672 2.268.864.952.304 1.82.26 2.508.16.764-.112 2.34-.956 2.672-1.88.332-.924.332-1.716.232-1.88-.1-.164-.364-.264-.76-.464z" fill="currentColor" data-astro-cid-iehx2mtc></path> </svg> <span class="whatsapp-label" data-astro-cid-iehx2mtc>Chat with me</span> </a> </body></html> <script> // Reading progress bar const progressBar = document.getElementById('reading-progress'); const returnToTop = document.getElementById('return-to-top'); function updateProgress() { const scrollTop = window.scrollY; const docHeight = document.documentElement.scrollHeight - window.innerHeight; const progress = docHeight > 0 ? scrollTop / docHeight : 0; progressBar.style.transform = 'scaleX(' + Math.min(progress, 1) + ')'; // Show/hide return to top button if (scrollTop > 600) { returnToTop.style.opacity = '1'; returnToTop.style.pointerEvents = 'auto'; } else { returnToTop.style.opacity = '0'; returnToTop.style.pointerEvents = 'none'; } } window.addEventListener('scroll', updateProgress, { passive: true }); updateProgress(); returnToTop.addEventListener('click', function() { window.scrollTo({ top: 0, behavior: 'smooth' }); }); </script>