{"schemaVersion":"1.0","type":"TechArticle","types":["Article","TechArticle"],"slug":"zero-friction-migration-how-to-import-your-existing-developer-blog-into-zyvop-huck5","url":"https://zyvop.com/zero-friction-migration-how-to-import-your-existing-developer-blog-into-zyvop-huck5","title":"Zero-Friction Migration: How to Import Your Existing Developer Blog into ZyVOP","subtitle":"Import from DEV, Hashnode, and Medium—or migrate Ghost and Substack through RSS and Hugo or Astro through Markdown ZIP, with canonical and image preservation where supported.","tldr":"An honest, technical guide to migrating your articles to ZyVOP across DEV, Hashnode, Medium, RSS feeds, and static-site Markdown archives, detailing exact platform support, image re-hosting, and canonical attribution.","keywords":["blogging","migrations","developer tools","ZyVOP","markdown","Tutorial","Building ZyVOP in Public"],"entities":["Sanju Singh","blogging","migrations","developer tools","ZyVOP","markdown","Tutorial","Building ZyVOP in Public"],"keyTakeaways":["Technical writing is one of the highest-leverage assets in software engineering.","Over time, however, developer portfolios become fragmented: early articles on DEV, corporate posts on Medium, a custom domain on Hashnode, or Markdown files in static site generators like Hugo, Astro, or Ghost.","Switching platforms often leads to broken syntax highlighting, mangled math formulas, orphan image references, duplicate cover photos, and canonical SEO dilution."],"headings":["1. Migration Support Matrix","2. Ingestion Pipelines: How It Works Under the Hood","A. Direct APIs (DEV &amp; Hashnode)","B. Universal RSS / Atom (Ghost, Substack, Medium)","C. Direct Web Article Extractor","D. Static-Site Markdown Archives (ZIP)","3. Duplicate Detection: Preventing Content Overwrites","4. How to Migrate: Step-by-Step","Option 1: Web Dashboard (Zero Installation)","Option 2: Uploading a Static Site ZIP","Option 3: Terminal Migration via the CLI (zyvop import)","5. Preflight Audits: The ZyVOP Compatibility Lab","6. Post-Migration: Establishing Sovereign GitOps"],"outboundLinks":[],"contentText":"Technical writing is one of the highest-leverage assets in software engineering. Over time, however, developer portfolios become fragmented: early articles on DEV, corporate posts on Medium, a custom domain on Hashnode, or Markdown files in static site generators like Hugo, Astro, or Ghost. Switching platforms often leads to broken syntax highlighting, mangled math formulas, orphan image references, duplicate cover photos, and canonical SEO dilution. ZyVOP was built as a sovereign developer publishing engine: write once, maintain canonical ownership, and distribute across ecosystems. But migrations are never one-size-fits-all. This guide provides an honest, technical look at how ZyVOP's import engine works, what is natively supported versus partially adapted, and how to migrate your catalog cleanly. 1. Migration Support Matrix Not every platform exposes identical APIs or export formats. ZyVOP supports migrations through four distinct ingestion pipelines: Source Migration Pathway Level of Support Key Technical Nuances DEV.to Native REST API First-Class Pulls published articles, markdown body, tags, canonical URLs, and original dates. Hashnode GraphQL API / Backup JSON First-Class Supports custom publication domains, backup JSON files, and RSS fallback. Medium Public RSS / Single URL Partial Ingests via public user feed; image re-hosting is disabled by default to avoid rate limits. Ghost Generic RSS / Single URL Partial Full text via RSS content:encoded. Native Ghost JSON archives are not yet parsed. Substack Generic RSS / Single URL Partial Imports published posts via RSS. Subscriber lists and paid tiers are not imported. Hugo / Jekyll Markdown ZIP Archive Partial Ingests .md and .markdown files with relative image re-hosting. Shortcodes require flattening. Astro / Next.js Markdown ZIP Archive Partial Supports standard Markdown. .mdx files and JSX/Astro components are ignored. 2. Ingestion Pipelines: How It Works Under the Hood flowchart TD subgraph Ingestion [\"1. Ingress Pipeline\"] DEV[\"DEV REST API\"] --&gt; API[\"Direct API Parser\"] HN[\"Hashnode GraphQL / JSON\"] --&gt; API RSS[\"RSS Feeds (Ghost / Substack / Medium)\"] --&gt; FeedParser[\"RSS 2.0 / Atom Engine\"] WEB[\"Single Article URL\"] --&gt; Readability[\"Mozilla Readability + DOM Filter\"] ZIP[\"Markdown ZIP (Hugo / Astro)\"] --&gt; ZipReader[\"Archive Extractor (.md / .markdown)\"] end subgraph Processing [\"2. Normalization &amp; Asset Engine\"] API --&gt; Norm[\"Content Normalizer\"] FeedParser --&gt; Norm Readability --&gt; Sharp[\"Perceptual Cover Deduplication (Sharp)\"] --&gt; Norm ZipReader --&gt; AssetRewrite[\"Relative Asset Re-hosting (S3/Cloud)\"] --&gt; Norm end subgraph Storage [\"3. Database &amp; Canonical Sync\"] Norm --&gt; Dedup{\"Duplicate Check\\n(Canonical URL / Title)\"} Dedup --&gt;|New Post| Draft[\"Saved Draft + Canonical Preservation\"] Dedup --&gt;|Exists| Skip[\"Skipped\"] endA. Direct APIs (DEV &amp; Hashnode) DEV.to: Connects via username or API key. Extracts raw Markdown directly, preserving original syntax fences, tags, and canonical links. Hashnode: Queries Hashnode's GraphQL endpoint across either personal subdomains (user.hashnode.dev) or custom publication apex domains. Also accepts native Hashnode JSON export backups (readHashnodeJson). B. Universal RSS / Atom (Ghost, Substack, Medium) Parses standard RSS 2.0, Atom, and content:encoded payloads. Image Re-hosting Nuance: For bulk RSS imports, image re-hosting is disabled by default (migrateImages = false) to prevent timeout failures and remote CDN rate-limiting across large archives. Remote image URLs are preserved as absolute URLs. C. Direct Web Article Extractor For standalone articles, ZyVOP executes an outbound fetch with Mozilla Readability, stripping boilerplate noise (.cookie-banner, .advertisement, .newsletter-signup, nav, footer). Perceptual Image Deduplication (Sharp): Many CMSs duplicate the social og:image as the first image in the post body. The single-URL extractor creates a 32×32 sRGB luminance fingerprint of the cover image and compares it against body images: // Bounded sRGB luminance and chromatic mean comparison in article-import-images.ts async function createImageFingerprint(data: Buffer): Promise&lt;ImageFingerprint&gt; { const pixels = await sharp(data, { limitInputPixels: 40_000_000 }) .resize(32, 32, { fit: 'fill' }) .toColourspace('srgb') .removeAlpha() .raw() .toBuffer(); // Evaluates luminance array and chromatic delta to strip duplicate hero images }D. Static-Site Markdown Archives (ZIP) When migrating from static site generators like Hugo, Astro, Jekyll, or Obsidian: Supported Formats: The reader accepts .md and .markdown files. Files with .mdx extensions or custom templates (.astro, .html) are ignored. Asset Re-hosting: References like ./images/diagram.png or ../assets/flowchart.webp are normalized through resolveArchiveAssetPath, uploaded to persistent storage, and rewritten in the Markdown body. Frontmatter Ingestion: Maps title, canonical_url (or canonicalUrl, url), cover_image, tags, and published_at. 3. Duplicate Detection: Preventing Content Overwrites ZyVOP avoids duplicate drafts during repeated syncs or CLI runs. Rather than relying on fragile hashes, the database executes a scoped uniqueness query: // Scoped duplicate check in markdown-zip-import.service.ts if (canonicalUrl) { const normalized = canonicalUrl.replace(/[?#].*$/, '').replace(/\\/+$/, ''); query.andWhere( '(post.canonicalUrl = :canonicalUrl OR post.canonicalUrl = :normalized OR post.canonicalUrl = :slash)', { canonicalUrl, normalized, slash: `${normalized}/` }, ); } else { query.andWhere('LOWER(TRIM(post.title)) = LOWER(TRIM(:title))', { title }); }If an article matches an existing post owned by the author, it is safely skipped rather than duplicated or overwritten. 4. How to Migrate: Step-by-Step Option 1: Web Dashboard (Zero Installation) Go to Dashboard → Migrate (/migrate). Select your source: DEV.to: Enter your username (devto/yourusername). Hashnode: Enter your publication domain (blog.yourdomain.com). Medium / Ghost / Substack: Paste your public profile or RSS feed URL (https://yourblog.com/rss.xml). Single URL: Paste a single article link to test readability extraction. Preview extracted articles, tags, and publication dates before committing them as drafts. Option 2: Uploading a Static Site ZIP In your Hugo/Astro/Jekyll repository, locate your Markdown directory. Ensure posts use standard Markdown (.md or .markdown). Convert .mdx component imports into standard code fences or markdown blocks. Zip the directory containing your posts and local image assets: zip -r blog-migration.zip content/posts/ assets/images/ Upload via Dashboard → Import → Upload Markdown ZIP. Option 3: Terminal Migration via the CLI (zyvop import) For developers who prefer terminal workflows: # Authenticate npx zyvop login # Import from DEV npx zyvop import devto yourusername # Import from Hashnode npx zyvop import hashnode blog.yourdomain.com5. Preflight Audits: The ZyVOP Compatibility Lab Before publishing or cross-posting imported drafts, inspect them in the ZyVOP Compatibility Lab (/compatibility-lab). The Compatibility Lab parses your article in-browser without modifying the database and runs preflight checks across destinations: Tag Truncation: Flags when your post exceeds destination limits (4 tags on DEV, 5 on Hashnode and Medium). Social Announcement Limits: Checks title and excerpt lengths against announcement constraints (180 characters for Bluesky, 320 for Mastodon). Local Asset Detection: Warns if an imported article still references non-public image paths (localhost or un-migrated relative paths). Syntax Adaptation: Reports how Mermaid diagrams and KaTeX formulas will adapt across each destination. 6. Post-Migration: Establishing Sovereign GitOps Once imported into ZyVOP, your articles are no longer locked into any single platform: Sovereign Canonical URL: Your ZyVOP publication acts as the primary authoritative source (&lt;link rel=\"canonical\"&gt;). Multi-Platform Distribution: Syndicate updates to DEV, Hashnode, Medium, and WordPress with one click or via npx zyvop publish. Automated Git Backup: Connect your GitHub account to have every post automatically committed to your personal repository via GitHub's Git Database API. Take sovereign ownership of your technical writing today without losing your hard-earned SEO equity or past article catalog.","contentHash":"sha256:7b7168aa3af7e55dd39443fd298264a0d32ebf6b97b21d116aa4e6d190155c6b","authorName":"Sanju Singh","authorUrl":"https://zyvop.com/author/sanjay687","authorSameAs":[],"category":"Tutorial","tags":["blogging","migrations","developer tools","ZyVOP","markdown"],"audience":"Software engineers and developers building applications with Tutorial","tone":"Instructional, practical, code-first","readingTimeMinutes":5,"wordCount":1147,"faqs":null,"primaryTopic":"Tutorial","publishedAt":"2026-10-18T05:28:09.253Z","updatedAt":"2026-10-18T05:28:09.253Z","canonicalUrl":"https://zyvop.com/zero-friction-migration-how-to-import-your-existing-developer-blog-into-zyvop-huck5"}