{"id":76624,"date":"2026-10-31T14:56:58","date_gmt":"2026-10-31T13:56:58","guid":{"rendered":"https:\/\/lumi-systems.io\/?p=76624"},"modified":"2026-10-31T15:31:50","modified_gmt":"2026-10-31T14:31:50","slug":"wix-to-hetzner-website-migration-bywiawithheart","status":"publish","type":"post","link":"https:\/\/lumi-systems.io\/en\/wix-to-hetzner-website-migration-bywiawithheart\/","title":{"rendered":"From Wix to Hetzner: A Complete Website Migration Case Study"},"content":{"rendered":"<style id=\"lumi-bywia-layout\">\n\/* bywia case study: wider reading column, full 16:9 header image *\/\n.postid-76624 .post-thumbnail.article-post-thumbnail{max-width:1500px!important;width:1500px!important;height:auto!important;padding-bottom:0!important;margin-left:auto!important;margin-right:auto!important;background:#071426;border-radius:0 0 18px 18px;overflow:hidden}\n.postid-76624 .post-thumbnail.article-post-thumbnail .post-thumbnail-inner{position:relative!important;height:auto!important;padding-bottom:0!important}\n.postid-76624 .post-thumbnail.article-post-thumbnail img{position:relative!important;left:auto!important;top:auto!important;width:100%!important;height:auto!important;max-height:none!important;object-fit:contain!important;display:block}\n.postid-76624 .entry-header,.postid-76624 .entry-content{max-width:1200px!important;margin-left:auto!important;margin-right:auto!important}\n@media(max-width:1300px){.postid-76624 .entry-header,.postid-76624 .entry-content{max-width:92%!important}.postid-76624 .post-thumbnail.article-post-thumbnail{max-width:96%!important;width:96%!important}}\n<\/style>\n<style id=\"lumi-article-css\">.lumi-article{--ink:#0f172a;--muted:#64748b;--line:rgba(15,23,42,0.1);--blue:#1a56db;--cyan:#06b6d4;--soft:#f8fafc;}.lumi-article p,.lumi-article ul,.lumi-article ol{font-size:17.5px;line-height:1.65;}.lumi-article p{margin:0 0 1.15em;text-wrap:pretty;}.lumi-article h2{margin:2.2em 0 0.8em;letter-spacing:-0.015em;}.lumi-article h3{margin:1.6em 0 0.5em;letter-spacing:-0.01em;}.lumi-article li{margin:0.35em 0;}.lumi-article li::marker{color:var(--blue);}.lumi-article a{text-underline-offset:2px;}.lumi-article .lumi-takeaways{background:linear-gradient(135deg,#eff6ff 0%,#f8fafc 65%);border:1px solid #bfdbfe;border-radius:18px;padding:22px 26px;margin:0 0 2.2em;max-width:100%;}.lumi-article .lumi-takeaways ul{margin:0;padding:0;list-style:none;display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:6px 28px;}.lumi-article .lumi-takeaways li{position:relative;padding-left:28px;margin:0.35em 0;font-size:16.5px;line-height:1.5;}.lumi-article .lumi-takeaways li::before{content:\"\u2713\";position:absolute;left:0;top:0.02em;color:#15803d;font-weight:800;}.lumi-article .lumi-stats{display:grid;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));gap:14px;margin:1.7em 0 2.1em;}.lumi-article .lumi-stat{background:var(--soft);border:1px solid var(--line);border-radius:16px;padding:18px 20px;}.lumi-article .lumi-stat-label{display:block;font-size:11px;font-weight:700;letter-spacing:0.14em;text-transform:uppercase;color:var(--blue);margin-bottom:8px;}.lumi-article .lumi-stat strong{display:block;font-size:32px;line-height:1.05;letter-spacing:-0.025em;color:var(--ink);}.lumi-article .lumi-stat span:last-child{display:block;margin-top:6px;font-size:14px;line-height:1.45;color:var(--muted);}.lumi-article .lumi-callout{border-radius:16px;padding:20px 24px;margin:1.8em 0;border:1px solid transparent;}.lumi-article .lumi-callout p:last-child{margin-bottom:0;}.lumi-article .lumi-callout-title{font-size:12px;font-weight:800;letter-spacing:0.13em;text-transform:uppercase;margin-bottom:0.55em;}.lumi-article .is-info{background:#eff6ff;border-color:#bfdbfe;}.lumi-article .is-info .lumi-callout-title{color:#1d4ed8;}.lumi-article .is-warning{background:#fff7ed;border-color:#fed7aa;}.lumi-article .is-warning .lumi-callout-title{color:#b45309;}.lumi-article .is-success{background:#f0fdf4;border-color:#bbf7d0;}.lumi-article .is-success .lumi-callout-title{color:#15803d;}.lumi-article .is-muted{background:var(--soft);border-color:var(--line);}.lumi-article .is-muted .lumi-callout-title{color:var(--muted);}.lumi-article .lumi-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(320px,1fr));gap:14px;margin:1.7em 0 2em;}.lumi-article .lumi-grid-2{grid-template-columns:repeat(2,minmax(0,1fr));}.lumi-article .lumi-grid-3{grid-template-columns:repeat(3,minmax(0,1fr));}.lumi-article .lumi-card{background:#ffffff;border:1px solid var(--line);border-radius:16px;padding:20px 22px;box-shadow:0 1px 2px rgba(15,23,42,0.04);}.lumi-article .lumi-card h3{margin:0.1em 0 0.45em;font-size:19px;line-height:1.25;}.lumi-article .lumi-card p{margin-bottom:0.55em;font-size:16px;line-height:1.55;}.lumi-article .lumi-card p:last-child{margin-bottom:0;}.lumi-article .lumi-card-num{display:inline-flex;align-items:center;justify-content:center;width:30px;height:30px;border-radius:50%;background:var(--blue);color:#fff;font-size:14px;font-weight:700;margin-bottom:10px;}.lumi-article .lumi-kicker{display:block;font-size:11px;font-weight:700;letter-spacing:0.14em;text-transform:uppercase;color:var(--muted);margin-bottom:4px;}.lumi-article .lumi-panel{border-radius:16px;padding:20px 24px;margin:1.7em 0;background:var(--soft);border:1px solid var(--line);}.lumi-article .lumi-panel h3{margin-top:0;font-size:18px;}.lumi-article .lumi-panel ul{margin-bottom:0;}.lumi-article .lumi-steps{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:12px;margin:1.7em 0 2em;}.lumi-article .lumi-step{background:var(--soft);border:1px solid var(--line);border-top:3px solid var(--blue);border-radius:12px;padding:15px 17px;}.lumi-article .lumi-step .lumi-step-num{display:block;font-size:11px;font-weight:700;letter-spacing:0.12em;text-transform:uppercase;color:var(--blue);margin-bottom:6px;}.lumi-article .lumi-step strong{display:block;font-size:16px;line-height:1.3;margin-bottom:4px;}.lumi-article .lumi-step p{margin:0;font-size:14.5px;line-height:1.5;color:var(--muted);}.lumi-article .lumi-table-scroll{max-width:100%;margin:1.6em 0 2em;}.lumi-article table{width:100%;border-collapse:collapse;font-size:15.5px;line-height:1.5;}.lumi-article thead th{text-align:left;vertical-align:bottom;padding:0 20px 10px 0;font-size:12px;font-weight:700;letter-spacing:0.07em;text-transform:uppercase;color:var(--muted);border-bottom:2px solid var(--ink);white-space:nowrap;}.lumi-article tbody td{text-align:left;vertical-align:top;padding:12px 20px 12px 0;border-bottom:1px solid var(--line);}.lumi-article tbody td:first-child{width:24%;font-weight:600;color:var(--ink);}.lumi-article tbody tr:nth-child(even) td{background:rgba(15,23,42,0.025);}.lumi-article tbody tr:hover td{background:rgba(26,86,219,0.05);}.lumi-article figcaption{text-align:left;font-size:14px;color:var(--muted);}@media (max-width:900px){.lumi-article .lumi-takeaways ul,.lumi-article .lumi-grid-2,.lumi-article .lumi-steps{grid-template-columns:1fr;}.lumi-article .lumi-grid{grid-template-columns:1fr;}.lumi-article table{font-size:14px;}.lumi-article thead th,.lumi-article tbody td{padding-right:14px;}.lumi-article tbody td:first-child{width:auto;}}.lumi-article h2[id],.lumi-article h3[id]{scroll-margin-top:100px;}.lumi-article .lumi-toc{background:#ffffff;border:1px solid var(--line);border-radius:16px;padding:18px 24px;margin:0 0 2.2em;}.lumi-article .lumi-toc-title{margin:0 0 0.7em;font-size:12px;font-weight:800;letter-spacing:0.13em;text-transform:uppercase;color:var(--muted);}.lumi-article .lumi-toc-title span{color:#94a3b8;font-weight:600;}.lumi-article .lumi-toc ol{margin:0;padding-left:1.2em;columns:2;column-gap:40px;font-size:15.5px;line-height:1.45;}.lumi-article .lumi-toc li{margin:0.28em 0;break-inside:avoid;}.lumi-article .lumi-toc a{color:var(--ink);text-decoration:none;}.lumi-article .lumi-toc a:hover{color:var(--blue);text-decoration:underline;}.lumi-article figure a{display:block;cursor:zoom-in;}.lumi-article figure a img{display:block;width:100%;height:auto;}@media (max-width:900px){.lumi-article .lumi-toc ol{columns:1;}}.lumi-article .lumi-cta{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:18px;background:linear-gradient(135deg,#0f172a 0%,#1e3a8a 100%);color:#f8fafc;border-radius:18px;padding:26px 30px;margin:2.4em 0 0;}.lumi-article .lumi-cta h2{color:#ffffff;margin:0 0 0.35em;font-size:24px;letter-spacing:-0.01em;}.lumi-article .lumi-cta p{color:#cbd5e1;margin:0;font-size:16px;line-height:1.5;max-width:760px;}.lumi-article .lumi-cta .lumi-cta-eyebrow{font-size:11px;font-weight:700;letter-spacing:0.14em;text-transform:uppercase;color:#93c5fd;margin-bottom:6px;}.lumi-article .lumi-cta .lumi-cta-link{display:inline-block;background:#ffffff;color:#0f172a;font-weight:700;font-size:16px;padding:12px 22px;border-radius:10px;text-decoration:none;white-space:nowrap;}.lumi-article .lumi-cta .lumi-cta-link:hover{background:#e2e8f0;color:#0f172a;}@media (max-width:900px){.lumi-article .lumi-cta{flex-direction:column;align-items:flex-start;padding:22px 22px;}.lumi-article .lumi-cta h2{font-size:21px;}}.lumi-article details.lumi-toc>summary{cursor:pointer;list-style:none;margin:0;}.lumi-article details.lumi-toc>summary::-webkit-details-marker{display:none;}.lumi-article details.lumi-toc>summary::after{content:\"\u25be\";float:right;color:#94a3b8;font-size:14px;}.lumi-article details.lumi-toc[open]>summary{margin-bottom:0.7em;}.lumi-article details.lumi-toc:not([open]){padding-bottom:18px;}.lumi-article .lumi-cta .lumi-cta-title{color:#ffffff;margin:0 0 0.35em;font-size:24px;line-height:1.25;letter-spacing:-0.01em;}@media (max-width:900px){.lumi-article .lumi-cta .lumi-cta-title{font-size:21px;}}.lumi-article figure.lumi-figure-mobile{max-width:430px;margin-left:auto;margin-right:auto;}.lumi-article figure.lumi-figure-mobile a,.lumi-article figure.lumi-figure-mobile img{width:100%;height:auto;}.lumi-article figure.lumi-figure-mobile figcaption{max-width:430px;font-size:13px;}@media (max-width:480px){.lumi-article figure.lumi-figure-mobile{max-width:100%;}}<\/style>\n<div class=\"lumi-article\">\n<p>bywiawithheart.com is a small Austrian brand with a clear promise: handmade bags and accessories, one piece at a time. The website had grown with the business, but it lived inside a closed website builder. That worked while the brand was small. It became a liability when the site needed to become a real business asset: own the domain, own the content, own the mailboxes, own the measurement, and know exactly who can change what.<\/p>\n<p>This is the story of moving the brand from Wix to a self-managed Hetzner stack \u2014 not as a lift-and-shift, but as a controlled migration across six layers: domain, DNS, website, email, analytics and secrets.<\/p>\n<div class=\"lumi-stats\">\n<div class=\"lumi-stat\"><span class=\"lumi-stat-label\">Platform<\/span><strong>1 stack<\/strong><span>Hetzner Cloud + Coolify + WordPress<\/span><\/div>\n<div class=\"lumi-stat\"><span class=\"lumi-stat-label\">Mailboxes<\/span><strong>4<\/strong><span>role-based addresses on one mail domain<\/span><\/div>\n<div class=\"lumi-stat\"><span class=\"lumi-stat-label\">Cutover<\/span><strong>staged<\/strong><span>DNS, TLS, mail and content verified before go-live<\/span><\/div>\n<\/div>\n<details class=\"lumi-toc\">\n<summary class=\"lumi-toc-title\">In this article <span>\u00b7 8 min read<\/span><\/summary>\n<ol>\n<li><a href=\"#the-brief\">The brief<\/a><\/li>\n<li><a href=\"#architecture\">The target architecture<\/a><\/li>\n<li><a href=\"#domain-dns-mail\">Domain, DNS and email<\/a><\/li>\n<li><a href=\"#website\">Rebuilding the website<\/a><\/li>\n<li><a href=\"#analytics\">Analytics without surveillance<\/a><\/li>\n<li><a href=\"#secrets\">Secrets and access<\/a><\/li>\n<li><a href=\"#operations\">Operations and go-live<\/a><\/li>\n<li><a href=\"#learned\">What we learned<\/a><\/li>\n<\/ol>\n<\/details>\n<h2 id=\"key-takeaways\">Key takeaways<\/h2>\n<div class=\"lumi-takeaways\">\n<ul>\n<li>A website migration is not a file copy. It is a coordinated change to domain, DNS, TLS, mail, content, analytics and access.<\/li>\n<li>Own the layers that create lock-in: the domain, the DNS zone, the content database, the email domain and the measurement.<\/li>\n<li>Stage in a separate environment; validate the production hostname, certificates, redirects and mail authentication before the public cutover.<\/li>\n<li>Self-hosted, cookieless analytics can answer the business question without a consent banner or a third-party tracker.<\/li>\n<li>Credentials belong in a secret manager, not in the repository, a spreadsheet or a chat. Infrastructure is not finished until it is observable and recoverable.<\/li>\n<\/ul>\n<\/div>\n<h2 id=\"the-brief\">The brief<\/h2>\n<p>The starting point was a working Wix site with a clear identity and a practical problem: the brand wanted a website it could evolve on its own terms, with professional email on its own domain and a measurement layer that respects visitors. \u201cMove it to Hetzner\u201d was the short version. The long version had five requirements:<\/p>\n<div class=\"lumi-grid lumi-grid-2\">\n<article class=\"lumi-card\"><span class=\"lumi-kicker\">01 \u00b7 Ownership<\/span><\/p>\n<h3>Own the domain and the content<\/h3>\n<p>The domain, DNS zone, WordPress database and media library must be under the client\u2019s control \u2014 not a side effect of a builder subscription.<\/p>\n<\/article>\n<article class=\"lumi-card\"><span class=\"lumi-kicker\">02 \u00b7 Continuity<\/span><\/p>\n<h3>Keep the brand recognizable<\/h3>\n<p>The new site had to feel like bywiawithheart: warm, handmade, personal \u2014 while improving speed, mobile navigation and editorial clarity.<\/p>\n<\/article>\n<article class=\"lumi-card\"><span class=\"lumi-kicker\">03 \u00b7 Communication<\/span><\/p>\n<h3>Mailboxes on the same domain<\/h3>\n<p>Role addresses for enquiries, orders and operations, with IMAP\/SMTP access and correct SPF, DKIM and DMARC.<\/p>\n<\/article>\n<article class=\"lumi-card\"><span class=\"lumi-kicker\">04 \u00b7 Measurement<\/span><\/p>\n<h3>Know what happens \u2014 without surveillance<\/h3>\n<p>Page views and acquisition channels are useful. A third-party advertising profile is not. The analytics choice had to fit Austrian privacy expectations.<\/p>\n<\/article>\n<\/div>\n<p>Those requirements shaped the architecture before a single page was rebuilt.<\/p>\n<h2 id=\"architecture\">The target architecture<\/h2>\n<p>We did not replace one monolith with another. The new platform separates concerns so each layer can be changed, observed and recovered independently:<\/p>\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https:\/\/lumi-systems.io\/wp-content\/uploads\/2026\/10\/architecture.png\" alt=\"Architecture diagram: Wix replaced by a Hetzner Cloud server with Coolify, WordPress, MariaDB, mail, Umami, Infisical and Vaultwarden\" \/><figcaption class=\"wp-element-caption\">One domain, one controlled stack: website, mail, analytics and secrets under a single operational model.<\/figcaption><\/figure>\n<div class=\"lumi-grid lumi-grid-3\">\n<article class=\"lumi-card\"><span class=\"lumi-kicker\">Compute<\/span><\/p>\n<h3>Hetzner Cloud<\/h3>\n<p>A dedicated virtual server with predictable resources and full root access. No shared-hosting surprises.<\/p>\n<\/article>\n<article class=\"lumi-card\"><span class=\"lumi-kicker\">Orchestration<\/span><\/p>\n<h3>Coolify<\/h3>\n<p>Services are deployed as reproducible containers; health, logs and domains are visible in one place.<\/p>\n<\/article>\n<article class=\"lumi-card\"><span class=\"lumi-kicker\">Application<\/span><\/p>\n<h3>WordPress + MariaDB<\/h3>\n<p>Editorial control stays with the client. The database and media library are portable and backed up.<\/p>\n<\/article>\n<article class=\"lumi-card\"><span class=\"lumi-kicker\">Edge<\/span><\/p>\n<h3>Traefik + Let\u2019s Encrypt<\/h3>\n<p>Automatic certificates, clean HTTPS and a single canonical hostname with a www redirect.<\/p>\n<\/article>\n<article class=\"lumi-card\"><span class=\"lumi-kicker\">Mail<\/span><\/p>\n<h3>Hetzner Mail<\/h3>\n<p>Role mailboxes with IMAP\/SMTP, plus SPF, DKIM and DMARC aligned to the sending domain.<\/p>\n<\/article>\n<article class=\"lumi-card\"><span class=\"lumi-kicker\">Measurement<\/span><\/p>\n<h3>Umami<\/h3>\n<p>Self-hosted, cookieless product analytics with a small team dashboard \u2014 no advertising profile.<\/p>\n<\/article>\n<\/div>\n<h2 id=\"domain-dns-mail\">Domain, DNS and email<\/h2>\n<p>The domain was the first dependency to remove. We transferred the registration to Hetzner and moved the authoritative DNS zone into the same account as the server and the mail system. That does not make the setup less redundant \u2014 it makes the responsibility explicit: one owner, one place to audit records.<\/p>\n<p>Before changing the public records we prepared the complete target zone: an A record for the apex and <code>www<\/code>, the MX record for the Hetzner mail server, SPF, DKIM and DMARC. The sequence mattered. TLS, mail and the website each depend on a different record being correct; changing them one by one without a checklist is how migrations produce \u201cit works on my laptop\u201d incidents.<\/p>\n<div class=\"lumi-grid lumi-grid-2\">\n<article class=\"lumi-card\"><span class=\"lumi-kicker\">Mail authentication<\/span><\/p>\n<h3>SPF, DKIM, DMARC<\/h3>\n<p>SPF authorizes the sending infrastructure. DKIM signs outgoing messages with a selector-specific key. DMARC tells receiving servers what to do when authentication fails and where to send aggregate reports.<\/p>\n<\/article>\n<article class=\"lumi-card\"><span class=\"lumi-kicker\">Mailboxes<\/span><\/p>\n<h3>Four role addresses<\/h3>\n<p>Personal, office, IT and webmaster mailboxes share the domain but not the purpose. Each has its own credentials, stored in the team vault \u2014 not in the website database.<\/p>\n<\/article>\n<\/div>\n<p>We verified the mail path in both directions: SMTP submission and IMAP retrieval, internal delivery, DNS records and message authentication. A mailbox that can receive but cannot send (or lands in spam) is not a finished mailbox.<\/p>\n<h2 id=\"website\">Rebuilding the website<\/h2>\n<p>The new website is a WordPress installation, but the design is deliberately not a generic theme demo. The visual system keeps the brand\u2019s warmth: generous whitespace, a calm palette, large product imagery and a clear path from \u201cwhat is this?\u201d to \u201cshow me the portfolio\u201d to \u201ccontact\u201d.<\/p>\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https:\/\/lumi-systems.io\/wp-content\/uploads\/2026\/10\/bywia-desktop-1600.png\" alt=\"The new bywiawithheart.com homepage on desktop\" \/><figcaption class=\"wp-element-caption\">The new homepage: brand first, product second, clear next step.<\/figcaption><\/figure>\n<div class=\"lumi-grid lumi-grid-2\">\n<article class=\"lumi-card\"><span class=\"lumi-kicker\">Editorial<\/span><\/p>\n<h3>Pages that answer a question<\/h3>\n<p>Home, about, offer, portfolio, gallery, price list and contact each have one job. The navigation reflects how a customer decides, not how the old site was organised.<\/p>\n<\/article>\n<article class=\"lumi-card\"><span class=\"lumi-kicker\">Mobile<\/span><\/p>\n<h3>Built for the phone first<\/h3>\n<p>Most visitors arrive from Instagram or a shared link. The mobile layout was checked at 390 px, with readable type, tappable targets and no horizontal squeeze.<\/p>\n<\/article>\n<\/div>\n<p>Content and media were migrated into the new installation, the WordPress address was set to the production domain, and internal links were checked after the search-and-replace. The staging hostname remained available during validation and was retired from the public path after acceptance.<\/p>\n<figure class=\"wp-block-image size-large lumi-figure-mobile\"><img decoding=\"async\" src=\"https:\/\/lumi-systems.io\/wp-content\/uploads\/2026\/10\/bywia-mobile.png\" alt=\"The new bywiawithheart.com homepage on a 390 pixel mobile screen\" \/><figcaption class=\"wp-element-caption\">The same story on a 390 px phone: readable, calm, one clear action.<\/figcaption><\/figure>\n<h2 id=\"analytics\">Analytics without surveillance<\/h2>\n<p>We replaced the old tracking with a self-hosted Umami instance on the same server. Umami records page views, referrers, devices and countries without cookies or cross-site profiles. For a small brand with Austrian and EU visitors, that is a much better fit than an advertising-driven analytics product.<\/p>\n<div class=\"lumi-grid lumi-grid-2\">\n<article class=\"lumi-card\"><span class=\"lumi-kicker\">Privacy<\/span><\/p>\n<h3>No consent banner by design<\/h3>\n<p>Cookieless measurement reduces the consent surface. The remaining configuration still matters: data minimisation, clear ownership and a defined retention policy.<\/p>\n<\/article>\n<article class=\"lumi-card\"><span class=\"lumi-kicker\">Team access<\/span><\/p>\n<h3>A dashboard, not a data silo<\/h3>\n<p>Both the client and Lumi get named accounts in a shared team. The canonical website ID is documented; duplicate dashboards are exactly the kind of detail that makes a team distrust the numbers.<\/p>\n<\/article>\n<\/div>\n<h2 id=\"secrets\">Secrets and access<\/h2>\n<p>A migration creates a new inventory of credentials: server access, database users, WordPress administrators, mailbox passwords, analytics accounts, DNS access. If those live in a note, a chat or a theme file, the migration has moved the website but not the risk.<\/p>\n<p>We use Infisical as the central secret store, with separate environments and a mirrored project for the client\u2019s instance. Vaultwarden holds the human-facing credentials the team uses day to day. The repository contains documentation and secret names, never secret values. DNS and mail records are documented next to the infrastructure, so the next person can verify a claim instead of guessing.<\/p>\n<div class=\"lumi-panel\">\n<p><strong>Rule of thumb:<\/strong> if a credential appears in a screenshot, a Git commit, a chat message or a browser autofill export, it is not a secret anymore. Rotate it, store it once and reference it by name.<\/p>\n<\/div>\n<h2 id=\"operations\">Operations and go-live<\/h2>\n<p>Go-live was a checklist, not a moment. Before the public cutover we verified:<\/p>\n<ul>\n<li>the production hostname resolves to the server and the server returns the expected site;<\/li>\n<li>the certificate chain is valid for the apex, <code>www<\/code> and the service subdomains;<\/li>\n<li><code>www<\/code> redirects to the canonical hostname without a redirect loop;<\/li>\n<li>MX, SPF, DKIM and DMARC are present and the mailboxes can send and receive;<\/li>\n<li>the analytics tracker is loaded from the production domain and records a test visit;<\/li>\n<li>DNS and HTTPS are monitored while the resolver caches settle;<\/li>\n<li>the client can log in and the team can recover access.<\/li>\n<\/ul>\n<p>We kept a rolling check on DNS and HTTPS during the cutover window and retired the transitional monitoring once the new state was stable. The important part is not the dashboard; it is knowing which signals would make us roll back.<\/p>\n<div class=\"lumi-grid lumi-grid-2\">\n<article class=\"lumi-card\"><span class=\"lumi-kicker\">What changed for the client<\/span><\/p>\n<h3>One accountable platform<\/h3>\n<p>Website, mail, analytics and secrets no longer depend on a website-builder subscription. The client owns the domain, the content and the accounts.<\/p>\n<\/article>\n<article class=\"lumi-card\"><span class=\"lumi-kicker\">What changed for operations<\/span><\/p>\n<h3>Boring, visible infrastructure<\/h3>\n<p>Containers with health checks, a documented DNS zone, Let\u2019s Encrypt renewal and a small, explicit credential inventory.<\/p>\n<\/article>\n<\/div>\n<h2 id=\"learned\">What we learned<\/h2>\n<p><strong>1. The migration order is the product.<\/strong> Domain, DNS, TLS, website and mail are coupled. A checklist with a named owner beats heroics on cutover night.<\/p>\n<p><strong>2. \u201cNo downtime\u201d is not a design goal; recoverability is.<\/strong> Resolver caches and TTLs are part of the change. We plan for propagation, verify from multiple resolvers and keep a rollback path.<\/p>\n<p><strong>3. Privacy can be an architecture decision.<\/strong> Cookieless analytics is not a feature bolted on at the end. It changes what data exists, which tools are allowed and what the client has to disclose.<\/p>\n<p><strong>4. Access is part of the deliverable.<\/strong> A site is not handed over until the client can log in, recover the account and understand which secret belongs to which service.<\/p>\n<p>The result is a website that is faster to operate, easier to explain and fully owned by the brand. The Wix subscription can end when the client is ready; the new platform does not depend on it.<\/p>\n<aside class=\"lumi-cta\">\n<div>\n<p class=\"lumi-cta-eyebrow\">Lumi-Systems.io<\/p>\n<h2 class=\"lumi-cta-title\">Planning a move off a closed website builder?<\/h2>\n<p>We migrate the domain, DNS, website, email, analytics and access as one controlled change \u2014 and document the result so your team can operate it.<\/p>\n<\/div>\n<p><a class=\"lumi-cta-link\" href=\"https:\/\/contact.lumi-systems.io\/\">Talk to us<\/a><\/p>\n<\/aside>\n<p>More engineering notes from our team: <a href=\"https:\/\/lumi-systems.io\/gitlab-ce-vs-premium-self-managed\/\">GitLab CE vs. Premium for a self-managed team<\/a>, <a href=\"https:\/\/lumi-systems.io\/sprint-planning-tool-for-gitlab-ce\/\">how we built capacity planning on GitLab CE<\/a>, and <a href=\"https:\/\/lumi-systems.io\/pm-suite-management-cockpit-gitlab-ce\/\">the PM-Suite management cockpit<\/a>.<\/p>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>How we moved bywiawithheart.com from Wix to a self-managed Hetzner stack \u2014 website, domain, DNS, email, analytics, secrets and operations in one controlled migration.<\/p>","protected":false},"author":2,"featured_media":76620,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_kad_post_transparent":"","_kad_post_title":"","_kad_post_layout":"","_kad_post_sidebar_id":"","_kad_post_content_style":"","_kad_post_vertical_padding":"","_kad_post_feature":"","_kad_post_feature_position":"","_kad_post_header":false,"_kad_post_footer":false,"_kad_post_classname":"","footnotes":""},"categories":[344,343],"tags":[428,426,421,424,423,425,427,420,422],"class_list":["post-76624","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-apps","category-lumi-systems-io","tag-case-study","tag-email-infrastructure","tag-hetzner","tag-infisical","tag-umami","tag-vaultwarden","tag-web-migration","tag-wix","tag-wordpress"],"_links":{"self":[{"href":"https:\/\/lumi-systems.io\/en\/wp-json\/wp\/v2\/posts\/76624","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/lumi-systems.io\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/lumi-systems.io\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/lumi-systems.io\/en\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/lumi-systems.io\/en\/wp-json\/wp\/v2\/comments?post=76624"}],"version-history":[{"count":4,"href":"https:\/\/lumi-systems.io\/en\/wp-json\/wp\/v2\/posts\/76624\/revisions"}],"predecessor-version":[{"id":76628,"href":"https:\/\/lumi-systems.io\/en\/wp-json\/wp\/v2\/posts\/76624\/revisions\/76628"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/lumi-systems.io\/en\/wp-json\/wp\/v2\/media\/76620"}],"wp:attachment":[{"href":"https:\/\/lumi-systems.io\/en\/wp-json\/wp\/v2\/media?parent=76624"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/lumi-systems.io\/en\/wp-json\/wp\/v2\/categories?post=76624"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/lumi-systems.io\/en\/wp-json\/wp\/v2\/tags?post=76624"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}