{"tool":"write","args":{"path":"PHAN_TICH_KIEN_TRUC_ECOMMERCE.md","content":"# Phân tích kiến trúc và hướng viết lại nền tảng e-commerce\n\n## Phạm vi và mức độ chắc chắn\n\nBáo cáo này phân biệt rõ ba loại kết luận:\n\n- Dữ kiện quan sát được: SPA React/Vite, REST API, Cloudflare, các biến hydration, endpoint và schema trong phần recon.\n- Suy luận kỹ thuật: cách dữ liệu và các module backend có khả năng phối hợp với nhau.\n- Đề xuất: kiến trúc source mới, không khẳng định đó là source hoặc công nghệ backend hiện tại.\n\nKhông thể xác định chắc backend dùng Node, PHP hay Python chỉ từ tên REST endpoint và JSON response. Muốn fingerprint đáng tin cậy hơn cần thêm response headers, cookie names, error format, CORS/preflight behavior, stack trace trong môi trường staging hoặc quyền truy cập deployment manifest.\n\n# 1. Kiến trúc vận hành hiện tại\n\n## 1.1 Bức tranh tổng thể\n\nSite đang theo mô hình ba lớp:\n\n1. Cloudflare/CDN và reverse proxy nhận request, phục vụ static assets đã hash và chuyển request động tới origin.\n2. React SPA build bằng Vite chịu trách nhiệm render giao diện, quản lý route và state phía trình duyệt.\n3. Backend REST riêng cung cấp catalog, CMS, store configuration và các nghiệp vụ như coupon, PayPal, contact, newsletter, review, tracking.\n\nĐây không phải WooCommerce, Shopify hay WordPress headless. Lý do kỹ thuật là API surface, product schema, settings và payment workflow đều mang hình dạng domain tự thiết kế, không giống REST namespace và resource conventions mặc định của các nền tảng đó.\n\nCloudflare không chứng minh origin dùng stack nào. Nó có thể che server headers, cache app-shell/static assets và proxy tới Node, PHP, Python hoặc nhiều service khác nhau.\n\n## 1.2 Luồng tải trang đầu tiên\n\nKhi người dùng mở /, /shop, /product/<slug> hoặc một route frontend khác, server trả cùng một app-shell có id=\"root\", các script /assets/index-<hash>.js và có thể có dữ liệu bootstrap trong window.__INITIAL_DATA__, window.__RC_HP, window.__RC_LAYOUT.\n\nLuồng hợp lý là:\n\n1. Trình duyệt nhận HTML app-shell.\n2. Trình duyệt tải JS/CSS có content hash; các file này có thể được cache lâu vì tên đổi khi build thay đổi.\n3. React khởi tạo tại #root và router đọc location.pathname để chọn page component.\n4. Page lấy dữ liệu bootstrap đã được nhúng, hoặc gọi REST API nếu dữ liệu đó thiếu/hết hạn.\n5. React dựng DOM và gắn event handlers.\n6. Các lần chuyển route nội bộ dùng History API, không tải lại toàn bộ document; chỉ component và data cần thiết thay đổi.\n\nĐiểm cần phân biệt: sự tồn tại của các biến window.__... chưa đủ chứng minh site có SSR thật. Nếu HTML chỉ chứa JSON và một root rỗng thì đây là bootstrap/preload cho CSR, không phải server-rendered product HTML. SSR chỉ tồn tại khi nội dung sản phẩm, heading, giá, link và metadata đã có trong HTML trước khi JS chạy.\n\nViệc mọi route trả cùng app-shell tạo trải nghiệm điều hướng SPA nhanh sau lần tải đầu, nhưng origin phải xử lý đúng fallback mà không biến URL không tồn tại thành HTTP 200. Nếu /product/khong-ton-tai cũng trả app-shell 200 và React chỉ hiển thị “not found”, crawler có thể coi đó là soft 404. Google cũng yêu cầu route CSR xử lý trạng thái lỗi hoặc noindex phù hợp để tránh soft 404 .\n\n## 1.3 Luồng dữ liệu catalog\n\nCác endpoint cho thấy frontend không mang catalog cố định trong bundle:\n\n-
GET /api/products?limit=500&active=1GET /api/products?q=...GET /api/products/<slug>GET /api/products/categorieslimit=500 là dấu hiệu API được tối ưu cho catalog nhỏ hơn là pagination lâu dài. Với 16 sản phẩm, tải một lần có thể đơn giản và nhanh; với hàng nghìn SKU, payload, thời gian query, bộ nhớ browser và việc invalidation cache sẽ tăng không cần thiết. Source mới nên dùng cursor pagination, field projection và endpoint riêng cho search/filter.\n\nProduct schema hiện tại có một số dấu hiệu “product-centric” thay vì “variant-centric”:\n\n- stock nằm ở product trong khi variants cũng tồn tại.\n- sizes, colors, genders vừa là mảng thuộc product, vừa có thể được lặp trong variants.\n- Dữ liệu có cả XXL và 2XL, cả ink navyInk Navyimage và images có khả năng trùng vai trò.\n- type, isbn có vẻ là trường generic hoặc được tái sử dụng từ domain khác.\n\nLý do đây là vấn đề kỹ thuật: tồn kho và SKU thực tế thuộc tổ hợp biến thể, ví dụ Black/M và Black/L phải trừ riêng; chuỗi option không chuẩn hóa làm filter, analytics và mapping ảnh theo màu thiếu ổn định. Viết lại nên chuẩn hóa option values, SKU và inventory ở cấp variant.\n\n## 1.4 Homepage builder\n\nsection_order cộng với object bật/tắt cho thấy homepage là một composition do CMS điều khiển, không phải thứ tự component hard-code hoàn toàn.\n\nMột renderer khả dĩ hoạt động như sau:\n\n1. /api/homepage trả configuration của các section.\n2. Frontend duyệt section_order.\n3. Mỗi key như hero, trustbar, catshowcase, promo, products được ánh xạ tới React component.\n4. Renderer kiểm tra toggle trước khi mount component.\n5. Component đọc payload tương ứng như ảnh, copy, CTA, product references hoặc thời hạn deal.\n\nĐiểm mạnh: marketing có thể đổi thứ tự và ẩn/hiện block mà không phát hành frontend. Lý do là thứ tự nằm trong data, còn frontend chỉ cung cấp component registry.\n\nĐiểm yếu: hiện tồn tại cả ann và announcement, cho thấy key alias hoặc schema migration chưa sạch. Nếu section_order, toggle và payload là ba cấu trúc rời nhau, chúng có thể lệch trạng thái: key có trong order nhưng không có payload, toggle dùng tên khác, hoặc payload tồn tại nhưng không được render.\n\nSource mới nên dùng một danh sách block duy nhất, trong đó mỗi block có id, kind, enabled, position, payload, schema_version. Cách này giữ thứ tự, trạng thái và dữ liệu trong cùng một aggregate, giảm lỗi đồng bộ.\n\n## 1.5 Layout builder và settings\n\n/api/layout nhiều khả năng chứa cấu hình header/footer/navigation, còn /api/public/settings chứa branding và store policy. Việc tách layout khỏi homepage là hợp lý vì header/footer dùng trên mọi route, trong khi homepage composition chỉ áp dụng cho trang chủ.\n\nDanh sách settings cho thấy một bảng key-value hoặc JSON config đang điều khiển:\n\n- thương hiệu và màu sắc;\n- logo/favicon;\n- thông tin doanh nghiệp;\n- phí và ngưỡng free shipping;\n- handling/transit windows;\n- payment provider và PayPal client ID;\n- social links, payment methods, navigation và announcement;\n- chiến dịch outerwear sale.\n\nƯu điểm: quản trị linh hoạt, thêm key không cần migration nếu dùng key-value/JSON.\n\nNhược điểm: key-value thuần túy thiếu type safety, foreign key và validation liên trường. Ví dụ standard_handling_min không được lớn hơn standard_handling_max; paypal_sandbox phải là boolean; URL social cần validation. Source mới nên dùng schema validation và chia public configuration khỏi secret/internal configuration.\n\ntax_id, địa chỉ pháp nhân, email vận hành hoặc thông tin không cần cho storefront không nên được trả hàng loạt qua public settings. PayPal client ID được phép public, nhưng client secret tuyệt đối chỉ ở server. Lý do là browser và mọi biến window.__... đều có thể bị người dùng đọc.\n\n## 1.6 Coupon và checkout PayPal\n\nLuồng thanh toán hợp lý:\n\n1. Client gửi giỏ hàng và coupon tới server.\n2. Server tải product/variant hiện hành từ database, kiểm tra active, stock và promotion.\n3. Server tự tính subtotal, discount, shipping, tax và grand total.\n4. /api/paypal/create-order tạo order trên PayPal bằng credential server-side và lưu quan hệ với checkout nội bộ.\n5. Client mở PayPal approval flow.\n6. /api/paypal/capture capture order đã được approve.\n7. Server xác minh amount/currency/status, tạo order chính thức, ghi payment attempt và trừ/reserve inventory.\n8. Webhook PayPal đối soát các trạng thái bất đồng bộ hoặc request bị ngắt.\n\nServer không được tin price, discount, shipping hoặc total do browser gửi. Lý do là người dùng có thể sửa request; server phải tính lại từ SKU, promotion rule và shipping method.\n\nHai endpoint create/capture là đúng hướng, nhưng chất lượng thực tế phụ thuộc vào:\n\n- idempotency key để double-click hoặc retry không tạo/capture hai lần;\n- transaction/locking để tránh oversell;\n- lưu payment attempt trước khi gọi provider;\n- xác minh webhook signature;\n- kiểm tra currency và amount;\n- state machine checkout rõ ràng;\n- reconciliation job cho trường hợp PayPal thành công nhưng response về site bị mất.\n\n## 1.7 Review, newsletter, contact và tracking\n\nCác endpoint này biến backend thành một commerce application thực thụ chứ không chỉ catalog API.\n\n- Review: cần trạng thái pending/approved/rejected, chống spam, rate limit và xác minh người mua nếu có nhãn verified purchase. POST /api/reviews/<id>POST /api/trackwindow.__INITIAL_DATA__ vào HTML cũng dễ thực hiện qua template hoặc middleware.\n\nTuy nhiên, đây chỉ là tương quan hệ sinh thái, không phải bằng chứng. REST route như /api/products/<slug> và snake_case fields không đặc trưng riêng của Node.\n\n### PHP với Laravel/Symfony hoặc framework nhẹ\n\nPHP vẫn hoàn toàn khả dĩ. Laravel dễ cung cấp REST controllers, database migrations, queue, mail, validation và có thể trả Vite app-shell từ một catch-all route. Cloudflare cũng có thể che toàn bộ dấu hiệu X-Powered-By hoặc cookie.\n\n### Python với FastAPI/Flask/Django\n\nPython cũng khả dĩ vì FastAPI/Flask dễ tạo JSON REST API, còn Django có ORM/admin mạnh. Vite build có thể được phục vụ bởi Nginx hoặc một static origin, độc lập với backend Python.\n\n### Kết luận fingerprint\n\nKhông đủ bằng chứng để chốt backend language. Dấu hiệu cần thu thập hợp pháp trong hệ thống của chính chủ sở hữu gồm deployment files, process manager, lockfile, container image, response headers chưa qua Cloudflare, cookie prefix, generated OpenAPI, error envelope và database driver. Không nên suy stack từ URL naming rồi coi đó là kết luận.\n\n## 1.10 Điểm mạnh kỹ thuật\n\n- UI độc lập nền tảng: React không bị ràng buộc bởi theme PHP hoặc page lifecycle của Woo; lý do là toàn bộ view layer nằm trong component tree riêng.\n- Static assets cache tốt: hash Vite cho phép Cache-Control: immutableproducts?limit=500 sẽ trở thành điểm nghẽn khi catalog lớn.\n\n### WooCommerce truyền thống\n\n- Trả HTML sản phẩm/category ngay từ server nên nội dung xuất hiện mà không đợi React boot.\n- Full-page cache, CDN, object cache và image optimization có thể làm storefront nhỏ rất nhanh.\n- Plugin nặng, theme nhiều JS, database query thiếu index và PHP worker thiếu tài nguyên có thể làm TTFB cao.\n- Cart, account và checkout là nội dung cá nhân hóa nên khó full-page cache hơn landing pages.\n\nKết luận: custom có trần hiệu năng cao hơn khi được SSR/SSG, cache và tối ưu bundle đúng; Woo có baseline đơn giản hơn. Không nên so bằng tên công nghệ. Hãy so p75 Core Web Vitals thực tế trên mobile, TTFB origin/CDN, JS transferred, API latency và error rate.\n\n## 2.3 Tùy biến UI và builder\n\nCustom React thắng rõ khi trải nghiệm thương hiệu cần animation, editorial block, campaign đặc thù hoặc component behavior không giống theme shop phổ thông. Lý do là đội phát triển kiểm soát markup, state, route transitions và design system.\n\nHomepage/layout builder tự viết cũng có thể gọn hơn plugin page-builder vì chỉ chứa 10–15 loại block được duyệt. Payload nhỏ hơn và editor ít lựa chọn sai hơn.\n\nWoo thắng về time-to-market và back-office. Product editor, order management, coupon, refund, tax/shipping integration và extension marketplace đã có sẵn. Muốn custom tương đương phải xây cả admin UX, validation, audit và migration, không chỉ storefront.\n\n## 2.4 SEO\n\nWoo truyền thống có lợi thế mặc định vì product/category HTML và metadata được server render. Pure client-rendered SPA không đồng nghĩa chắc chắn “không index”: Google có thể render JavaScript, nhưng nội dung vẫn phụ thuộc rendering queue, API availability, route semantics và internal links.\n\nRủi ro thực tế của pure SPA gồm:\n\n- HTML ban đầu thiếu product name, description và structured data;\n- title/canonical/Open Graph cập nhật sau JS nên bot mạng xã hội có thể bỏ lỡ;\n- catch-all trả 200 cho URL lỗi;\n- API bị chặn, timeout hoặc hydration lỗi làm crawler thấy trang rỗng;\n- pagination/filter tạo URL không canonical;\n- links được tạo bằng click handler thay vì <a href>. Vì vậy source mới không nên chỉ thêm dịch vụ “render riêng cho bot”.\n\nCách khắc phục đúng:\n\n1. SSG/ISR product, category, content và homepage để HTML có nội dung ngay.\n2. SSR các route cần dữ liệu theo request.\n3. Dùng CSR chỉ cho cart drawer, personalization và tương tác sau tải.\n4. Sinh metadata, canonical, JSON-LD Product/Breadcrumb/Organization ở server.\n5. Trả 404/410 thật cho resource không tồn tại.\n6. Có XML sitemap, robots policy, pagination và redirects khi đổi slug.\n7. Test bằng rendered HTML, Search Console và crawler không chạy JS.\n\n## 2.5 Bảo trì\n\n### Custom\n\nPhải bảo trì frontend, backend, database, admin, API contract, payment integration, email jobs, cache và deployment. Một thay đổi field có thể ảnh hưởng nhiều client. Cần contract tests, migrations backward-compatible và observability.\n\nĐổi lại, chỉ có code cần thiết; không phải xử lý xung đột hàng chục plugin. Đội sở hữu toàn bộ roadmap và có thể xóa legacy.\n\n### WooCommerce\n\nCore commerce và admin được cộng đồng/vendor duy trì, nhưng phải cập nhật WordPress core, Woo, theme và plugins. Mỗi update cần staging test vì hooks, template overrides và plugin compatibility có thể thay đổi.\n\nKết luận: Woo chuyển chi phí từ “tự xây domain” sang “quản lý ecosystem”; custom chuyển chi phí từ plugin license/compatibility sang engineering payroll và vận hành.\n\n## 2.6 Chi phí hosting\n\nWoo nhỏ có thể chạy trên một managed WordPress host, database và CDN, nên đơn giản về hóa đơn và vận hành. Custom SPA có frontend static rất rẻ, nhưng tổng hệ thống vẫn cần API compute, database, object storage, email, queue, logs và backup.\n\nDo đó custom không mặc nhiên rẻ hơn. Ở traffic thấp, chi phí con người và số service thường lớn hơn tiền compute. Ở traffic đọc cao, static/edge rendering của headless có thể giảm tải origin đáng kể.\n\n## 2.7 Khả năng mở rộng\n\nCustom tách frontend khỏi backend nên có thể scale CDN, read API, worker và database độc lập. Đây là lợi thế nếu traffic campaign tăng mạnh hoặc có nhiều channel dùng cùng commerce API.\n\nNhưng scaling checkout không chỉ là thêm server. Database transaction, inventory reservation, payment idempotency, webhook ordering và cache consistency mới là phần khó.\n\nWoo có thể phục vụ quy mô đáng kể nếu dùng hosting tốt, cache, database tuning và ít plugin. Điểm nghẽn thường xuất hiện ở request động, query/meta table, plugin hooks và PHP worker. Với 16 sản phẩm, chưa có bằng chứng quy mô hiện tại buộc phải dùng custom microservices.\n\n## 2.8 Lệ thuộc plugin và vendor\n\nWoo phụ thuộc plugin nhiều hơn nếu mọi tính năng được ghép từ extension; rủi ro là license, update cadence, abandoned plugin và xung đột hook.\n\nCustom giảm phụ thuộc plugin WordPress nhưng không loại bỏ dependency: vẫn phụ thuộc framework, npm packages, cloud/CDN, PayPal SDK, email provider và đội phát triển. Đây là thay đổi loại phụ thuộc, không phải không còn phụ thuộc.\n\n## 2.9 Bảng quyết định\n\n| Tiêu chí | Custom React + REST hiện tại | Woo truyền thống | Custom SSR/ISR đề xuất |\n|---|---|---|---|\n| UI thương hiệu | Rất linh hoạt | Phụ thuộc theme/builder | Rất linh hoạt |\n| SEO mặc định | Rủi ro nếu CSR thuần | Tốt hơn do HTML server-side | Tốt nếu metadata/status đúng |\n| Điều hướng sau tải | Nhanh | Full navigation truyền thống | Nhanh, có progressive enhancement |\n| First view | Có thể vướng JS/API | Có HTML ngay | Có HTML ngay và hydrate chọn lọc |\n| Back-office | Phải tự xây | Trưởng thành | Phải tự xây hoặc dùng commerce engine |\n| Bảo trì | Engineering cao | Update/plugin cao | Engineering cao nhưng kiến trúc tốt hơn |\n| Mở rộng nhiều channel | Tốt | Cần REST/headless layer | Tốt |\n| Phù hợp catalog 16 sản phẩm | Có thể dư kiến trúc | Rất phù hợp | Phù hợp nếu thương hiệu/roadmap biện minh |\n\n## 2.10 Khuyến nghị lựa chọn\n\n- Nếu mục tiêu là ra mắt nhanh, đội nhỏ, quy trình commerce tiêu chuẩn và không cần UX quá riêng: dùng WooCommerce truyền thống với theme nhẹ, ít plugin, managed hosting và cache tốt.\n- Nếu mục tiêu là sở hữu trải nghiệm thương hiệu, builder riêng, tích hợp nhiều channel và đội có năng lực backend/payment: tiếp tục hướng custom, nhưng thay pure SPA bằng framework SSR/SSG/ISR.\n- Không khuyến nghị “headless Woo” chỉ để nghe hiện đại nếu vẫn phải vận hành cả WordPress lẫn frontend mà không có nhu cầu UI/channel rõ ràng. Nó kết hợp hai mặt chi phí.\n\nĐối với site này, hướng hợp lý nhất là giữ tư duy custom commerce nhưng viết storefront mới theo hybrid rendering, không sao chép SPA hiện tại và không nhất thiết chuyển sang Woo. Lý do là builder và brand UI đã là năng lực cốt lõi; phần cần sửa là rendering, data model, checkout correctness và vận hành.\n\n# 3. Hướng viết lại thành source mới\n\n## 3.1 Nguyên tắc\n\nSource mới nên tái sử dụng yêu cầu nghiệp vụ và dữ liệu mà chủ sở hữu có quyền dùng, nhưng không sao chép bundle decompiled, cấu trúc module, tên private symbol hoặc implementation cũ.\n\nCó thể tái sử dụng các ý tưởng phổ quát:\n\n- catalog/category/product detail;\n- homepage theo block;\n- layout có header/footer/nav;\n- coupon, newsletter, contact, reviews, tracking;\n- PayPal create/approve/capture;\n- shipping tiers và store settings.\n\nNên làm mới:\n\n- route naming và response envelopes;\n- database model variant/inventory;\n- component registry và builder schema;\n- rendering strategy;\n- checkout state machine;\n- cache invalidation;\n- security, observability và test suite.\n\n## 3.2 Stack đề xuất\n\n### Storefront\n\n- Next.js App Router + React + TypeScript để có server components, SSR, static generation/ISR và client components ở vùng tương tác.\n- Zod cho validation contract ở boundary.\n- TanStack Query chỉ cho state server-side cần refresh phía client, không fetch lại dữ liệu đã render nếu không cần.\n- CSS Modules/Tailwind hoặc design-token system; chọn một chuẩn và giới hạn runtime CSS-in-JS.\n- Image optimization qua CDN/object storage với width/format rõ ràng.\n\nNext.js không phải lựa chọn duy nhất; Remix hoặc framework SSR tương đương cũng phù hợp. Tiêu chí quan trọng là HTML server-rendered, status code đúng, cache có kiểm soát và ít JS client, không phải brand framework.\n\n### Backend\n\n- NestJS với Fastify adapter + TypeScript, hoặc Fastify module hóa nếu đội muốn ít abstraction.\n- PostgreSQL làm source of truth.\n- Drizzle ORM hoặc Prisma cho migrations và type-safe query; các transaction payment/inventory vẫn cần thiết kế thủ công.\n- Redis chỉ khi thật sự cần cache, distributed lock hoặc rate-limit; không đưa Redis vào ngày đầu nếu một instance và traffic nhỏ đủ dùng.\n- BullMQ/queue tương đương cho email, webhook retry, analytics và reconciliation.\n- S3-compatible object storage cho media; database chỉ lưu metadata/key.\n- OpenTelemetry + structured logs + error tracking để nối request, checkout và payment attempt.\n\n### Deployment\n\n- Storefront đặt sau CDN/edge cache.\n- API chạy container/service riêng.\n- PostgreSQL managed với point-in-time recovery.\n- Object storage tách khỏi container filesystem.\n- Preview/staging dùng PayPal sandbox và database riêng.\n- Secrets qua secret manager, không nằm trong repo
Studio Global AI
Use this topic as a starting point for a fresh source-backed answer, then compare citations before you share it.
{"tool":"write","args":{"path":"PHAN TICH KIEN TRUC ECOMMERCE.md","content":" Phân tích kiến trúc và hướng viết lại nền tảng e commerce\n\n Phạm vi và mức độ chắc chắn\n\nBáo cáo này phân biệt rõ ba loại kết luận:\n\n Dữ kiện quan sát được:
{"tool":"write","args":{"path":"PHAN TICH KIEN TRUC ECOMMERCE.md","content":" Phân tích kiến trúc và hướng viết lại nền tảng e commerce\n\n Phạm vi và mức độ chắc chắn\n\nBáo cáo này phân biệt rõ ba loại kết luận:\n\n Dữ kiện quan sát được: Muốn fingerprint đáng tin cậy hơn cần thêm response headers, cookie names, error format, CORS/preflight behavior, stack trace trong môi trường staging hoặc quyền truy cập deployment manifest.\n\n 1.
Kiến trúc vận hành hiện tại\n\n 1.1 Bức tranh tổng thể\n\nSite đang theo mô hình ba lớp:\n\n1.