Skip to content

Di chuyển WordPress → KDIGI CMS / Migrating WordPress → KDIGI CMS

View markdown

English summary. KDIGI CMS ships a generic, idempotent, 8-phase pipeline that moves any WordPress site (posts, pages, categories/tags/custom taxonomies, media, menus, authors, comments, Yoast and RankMath SEO, redirects, optional WooCommerce products) into one KDIGI site. Data flows WordPress → raw/ (immutable mirror) → staged/ (editable JSON) → review gate → Payload. Nothing is written to the database before an editor locks the staged data (--gate lock), and any non-local database is pg_dump-ed first (no skip flag). Start with the runbook (step-by-step commands) and use the playbook to decide how to handle your WordPress setup (Yoast vs RankMath, Gutenberg/Elementor/Classic, WooCommerce, Polylang/WPML, big media libraries, known pitfalls).

Tài liệu này mô tả pipeline di chuyển nội dung từ bất kỳ site WordPress nào sang KDIGI CMS. Pipeline nằm ở src/importers/run-wp-migration.ts (điều phối), src/importers/wp-migration/** (chuẩn hóa + các phase) và src/scripts/wp-archive-* (tải dữ liệu nguồn).

Tài liệuDùng khi
runbook.mdBạn cần lệnh chạy từng bước từ con số 0: chuẩn bị, archive, review, import, kiểm tra, rollback
playbook.mdBạn cần quyết định: site của bạn dùng Yoast hay RankMath, Elementor hay Gutenberg, có WooCommerce / đa ngôn ngữ / thư viện media lớn không, và các lỗi đã biết
Nguồn WordPressĐích KDIGIGhi chú
postpostsNội dung → Markdown (contentMd), ngày xuất bản giữ nguyên
pagepagesPage lồng nhau được làm phẳng theo slug; có redirect từ URL cũ
category, post_tagtaxonomies (category, tag)Giữ cây cha/con
Taxonomy tùy biến (genre, brand…)taxonomies (custom + customType)customType = tên taxonomy gốc
WooCommerce product, product_cat, product_tagproducts, taxonomies (product-category, tag)Tùy chọn; một giá chung (prices[0]), gallery → hero.slider
Custom post type khácposts / pages / productsKhai báo bằng --cpt <type>=<collection>
Media LibrarymediaBinary tải về từ REST; local-disk hoặc R2 tùy cấu hình storage
MenumenusCây nhiều cấp; map vị trí WP → PRIMARY / FOOTER_MENU / …
Tác giảauthorsLấy từ bài viết (+ /users nếu REST cho phép)
Bình luậncommentsBình luận của post/product; bình luận spam giữ trạng thái spam
Yoast SEO / RankMathseo.* của từng docTitle, description, canonical, robots, Open Graph, twitter, focus keyword
Logo, favicon, JSON-LD Organization, link mạng xã hộisites.branding, sites.knowledgeGraph, sites.socialProfilesChỉ điền phần WordPress thực sự sở hữu
Permalink cũredirects (301)Tự sinh khi đường dẫn đổi; thêm tay qua staged/redirects/

Không di chuyển: theme/giao diện, plugin, cấu hình form, người dùng đăng nhập WP, nội dung do page builder lưu ngoài post_content (xem playbook).

┌────────────┐ archive ┌───────────────────────┐ normalize ┌──────────────────────┐
│ WordPress │ ───────────▶ │ wp-archive/<site>/raw │ ──────────▶ │ wp-archive/<site>/ │
│ REST / │ (bước 1) │ rest/ content/ │ (bước 2) │ staged/<collection>/│
│ WPGraphQL │ │ media/files/ │ │ *.json (1 file/doc) │
└────────────┘ └───────────────────────┘ └──────────┬───────────┘
│ review + sửa tay (bước 3)
▼
--gate lint ──▶ --gate lock ──▶ .gate-lock (hash nội dung)
│
┌── backup gate: DB không phải local ⇒ pg_dump bắt buộc ──┐
▼ │
schema ▶ seed ▶ taxonomy ▶ content ▶ media ▶ seo ▶ nav ▶ comments ▶ redirects ◀───────┘
(bước 4: import, idempotent, chạy lại được, có --dry-run)
  1. Archive — tải bản chụp nguồn. Ưu tiên WPGraphQL nếu site có; nếu không, dựng từ REST API chuẩn của WordPress (chạy được trên mọi site). raw/ là bản sao nguồn, không sửa tay.
  2. Normalize — chuyển raw/ thành staged/: HTML → Markdown, SEO của Yoast/RankMath → một schema thống nhất, taxonomy/menu/author/media/comment, đường dẫn nguồn cho redirect.
  3. Review gate — con người rà soát và sửa staged/, --gate lint phải sạch, --gate lock ghi hash nội dung. Sửa staged/ sau khi lock sẽ làm lock mất hiệu lực.
  4. Import — 8 phase ghi vào Payload, mỗi phase kiểm lại lock; ghi vào DB không phải local luôn pg_dump trước.
#PhaseViệc làm
0schemapnpm payload migrate rồi kiểm các giá trị enum mà importer cần (không chạy khi --dry-run; vẫn đọc DB)
1seedTạo Site nếu chưa có (không bao giờ ghi đè Site có sẵn) + tạo tác giả
2taxonomyUpsert category / tag / product-category / custom, nối cây cha–con
3contentUpsert pages / posts / products (+ FAQ, rating, giá); giữ publishedAt của WP
4mediaTải/tạo media, gắn featured image, gallery, ảnh OG, ghi lại URL ảnh trong thân bài
5seoÁp lại nhóm seo (canonical, robots, OG, twitter, article dates)
6navMenu, cấu hình site (logo, favicon, knowledge graph, social), FAQ
7commentsBình luận của post/product
8redirects301 từ permalink WP cũ → đường dẫn mới + các dòng thủ công

schema là bước chuẩn bị DB; 8 phase ghi dữ liệu là seed → redirects. Danh sách phase nằm ở IMPORT_PHASES trong src/importers/wp-migration/wp-migration-config.ts.

Cấu hình: cờ CLI và biến môi trường

Section titled “Cấu hình: cờ CLI và biến môi trường”

Không có tên site, host hay đường dẫn cứng trong mã: mọi thứ qua cờ CLI hoặc env.

CờÝ nghĩa
--site <siteKey>Sites.siteKey (a–z, 0–9, -) và tên thư mục wp-archive/<siteKey>/ — bắt buộc
--wp-url <https://wp.example.com>Origin của backend WordPress (REST/GraphQL) — bắt buộc trừ --gate status
--domain <example.com>Domain công khai mới (ghi vào Sites.domain, viết lại canonical/OG)
--public-url <https://www.example.com>Host công khai của site WP cũ nếu khác --wp-url (để đổi link nội bộ thành đường dẫn tương đối)
--lang vi|enNgôn ngữ site (mặc định vi); site đa ngôn ngữ chỉ giữ ngôn ngữ này
--archive, --archive-via auto|graphql|restTải lại archive / chọn nguồn
--regen-stagedDựng lại staged/ từ raw/ (ghi đè chỉnh sửa tay, có hỏi xác nhận)
--cpt <type>=<posts|pages|products>[,…]Nhập custom post type
--only media,…Chỉ normalize các collection nêu tên
--gate lint|lock|statusCổng review
--from <phase> --to <phase>Chạy khoảng phase import (không có ⇒ không import)
--media-urls cms|sourceẢnh trong thân bài trỏ về URL của CMS (mặc định) hay giữ URL nguồn
--dry-run, --yesXem trước không ghi / bỏ câu hỏi xác nhận
Biến môi trườngÝ nghĩa
DATABASE_URIPostgres đích (bắt buộc cho import)
WP_AUTH_USER, WP_AUTH_PASSWORDWordPress Application Password — tùy chọn, mở khóa media riêng tư, menu, users
WP_POST_TYPESDanh sách post type bổ sung cần archive, ví dụ portfolio,event
WP_UTC_OFFSETMúi giờ của WordPress khi API trả ngày không kèm offset, ví dụ +07:00 (mặc định +00:00)
KDIGI_LOCAL_DB_HOSTSHostname Postgres được coi là local (ví dụ postgres trong docker compose)
BACKUP_DIRThư mục lưu file pg_dump (mặc định backups-local/)
GATE_APPROVERTên người duyệt ghi vào .gate-lock (mặc định user hệ điều hành)

src/importers/wp-migration/prod-backup-gate.ts: nếu host của DATABASE_URI không thuộc localhost / 127.0.0.1 / ::1 / host.docker.internal / KDIGI_LOCAL_DB_HOSTS — hoặc URI không phân tích được — orchestrator hỏi xác nhận rồi chạy pg_dump -Fc vào backups-local/. Dump lỗi hoặc rỗng ⇒ dừng. Không có cờ bỏ qua; --yes chỉ bỏ câu hỏi; --dry-run không ghi nên không dump. Cần pg_dump (gói postgresql-client) khớp phiên bản server.

Đường dẫnVai trò
src/importers/run-wp-migration.tsCLI điều phối
src/importers/wp-migration/wp-migration-config.tsCấu hình site, đường dẫn, danh sách phase, map taxonomy
src/importers/wp-migration/raw-wp-types.tsHợp đồng dữ liệu raw/content/*.json
src/importers/wp-migration/staged-doc-types.tsHợp đồng dữ liệu staged/**
src/importers/wp-migration/normalize-raw-to-staged.ts, seo-to-staged.tsBước 2
src/importers/wp-migration/staged-gate.ts, release-content-policy.tsBước 3 (lint/lock, denylist media)
src/importers/wp-migration/phase-*.tsBước 4
src/importers/wp-html-to-gfm*.tsBộ chuyển HTML → Markdown
src/importers/regen-jsonld.ts, seed-default-authors.tsCông cụ bảo trì độc lập
src/scripts/wp-archive-*.tsBước 1