Mục lục bài viết24 mục
- 1.Mục tiêu sản phẩm và luồng người dùng
- 2.Yêu cầu chức năng bắt buộc (MVP)
- 3.Đề xuất kiến trúc kỹ thuật tổng quan
- 4.Stack frontend và công nghệ UI đề xuất
- 5.Template engine và mapping nội dung
- 6.Thiết kế hệ thống template và component tái dùng
- 7.Bộ 8 mẫu minh họa (4 sức khỏe, 4 làm đẹp)
- 8.Mẫu dữ liệu đầu vào và JSON Schema mẫu
- 9.Giao diện chọn và quản lý template, import/export
- 10.Trình soạn thảo nội dung và validation
- 11.Trình soạn thảo nội dung và validation
- 12.Responsive design system và breakpoints + lỗi thường gặp
- 13.Export static HTML/CSS: build pipeline và packaging
- 14.SEO cơ bản, performance và accessibility checklist
- 15.Form và lead capture integration options
- 16.Testing, QA và visual regression
- 17.Hướng dẫn triển khai prototype và packaging cho Windows/macOS
- 18.Security, privacy và lưu trữ local-first
- 19.Extensibility: marketplace, plugin helpers, migration và versioning
- 20.Compliance workflow cho nội dung sức khỏe và làm đẹp
- 21.Risk register và mitigation kế hoạch
- 22.Roadmap phát triển và milestones cho prototype → production
- 23.Tài liệu cần viết kèm và checklist handover
- 24.Kết luận
Mình trình bày lộ trình kỹ thuật và checklist để bạn thiết kế một ứng dụng PC local-first giúp marketer chọn template (8 mẫu minh họa: 4 sức khỏe, 4 làm đẹp), nhập nội dung, preview responsive và xuất HTML/CSS tĩnh. Có đề xuất kiến trúc Electron/Tauri, pipeline media, validation và export.
Mục tiêu sản phẩm và luồng người dùng
Mục tiêu MVP: một ứng dụng PC để người dùng nội bộ hoặc marketer nhanh tạo sale page responsive từ nội dung có sẵn, chọn từ thư viện template chủ đề sức khỏe và làm đẹp, tùy chỉnh nhanh (hình, văn bản, màu, font), preview chính xác trên nhiều kích thước, xác thực các ràng buộc bắt buộc, và xuất ra bộ file HTML/CSS/asset tĩnh sẵn deploy. Ứng dụng lưu dự án local theo định dạng JSON + folder assets, có export ZIP cho deploy. Actors chính: developer chịu kỹ thuật và tích hợp, product manager (PM) điều phối yêu cầu và kiểm tra QA, marketer nhập nội dung và xuất bản.
Luồng người dùng chính (high-level)
- Tạo project mới
- Chọn template theo chủ đề
- Nhập và chỉnh nội dung (form + inline + markdown)
- Preview responsive (desktop/tablet/mobile)
- Validate (schema, media, compliance heuristics)
- Export tĩnh (folder + ZIP) hoặc save draft local
Luồng hành vi chi tiết để dev/PM dùng làm checklist
- Create project
- UI: màn hình New Project with fields: project name, slug (auto gợi ý), target country, export mode (light/self-contained).
- Local state: create folder structure in workspace/projects/<slug>/ with project.json, assets/.
- Checklist dev:
- create atomic save API (saveProject, loadProject) with versioned project.json (field projectVersion).
- ensure file locking / concurrency safe for autosave.
- surface immediate validation errors if slug invalid.
- Choose template
- UI: Template Library filtered by category (Sức khỏe, Làm đẹp), search, preview thumbnails, tags.
- Action: user selects template -> app clones template package into project/templates/active/ and loads template manifest.
- Checklist dev/PM:
- manifest validation: template must include template.json with requiredFields and themeVariables.
- import logic must copy partials, css, preview assets.
- if template requires compliance review, mark project.settings.requiresCompliance = true.
- Nhập nội dung
- Modes available:
- Structured form: right-side panel lists fields defined in template manifest. Types: text, richtext (markdown), image, list, boolean, url.
- Inline editing: click on canvas to edit text; drag-drop images into placeholders.
- Bulk import: upload JSON/CSV to map fields (mapping UI with preview).
- UX rules:
- every edit updates in-memory project.model and triggers debounce autosave to disk.
- image drops copy file to assets/ and create placeholder derivatives for preview.
- Checklist dev:
- implement two-way binding between form fields and template context paths.
- sanitize and normalize pasted HTML; store rich text as sanitized HTML or markdown.
- on image import, capture intrinsic width/height and store metadata in project.json.
- provide undo/redo stack per project session.
- Preview
- UI: central canvas showing rendered template with toolbar to switch breakpoints: Desktop/Tablet/Mobile and toggle show/hide overlays (grid, spacing, alt-text warnings).
- Behavior:
- render pipeline uses template engine to compile with current project.model and themeVariables.
- preview must reflect exactly what export will produce for HTML structure and CSS variables.
- Checklist dev:
- isolated render sandbox separate from editor to avoid style bleed.
- implement viewport simulation and device emulation for densities.
- include visual indicators for missing required fields inline.
- ensure preview uses same image srcset logic as export.
- Validate (preflight)
- Types of validation:
- Schema validation: project.model against template manifest/JSON Schema; list missing required fields.
- Media validation: check image minimum dimensions/aspect ratios per manifest, file size warnings.
- Content heuristics: keyword scanner for risky health claims, presence of mandatory disclaimer for health templates.
- Export readiness: all relative asset refs resolvable.
- UI: preflight panel with two sections: blocking issues and warnings. Blocking issues must be fixed before final export unless user forces export with explicit acknowledgment.
- Checklist dev/PM:
- implement ajv or similar JSON Schema validator and map errors to UI paths.
- define clear severities: BLOCKER, WARNING, INFO.
- produce actionable messages: field path, expected type, remediation suggestion.
- log preflight runs for audit (timestamp, user id, issues).
- Export
- Options: Export Light (references external CDN fonts/images), Export Self-contained (includes all assets, fonts, webp variants).
- Steps executed by app:
- run final render to produce index.html,
- generate srcset/webp variants from stored assets,
- inject meta tags and theme CSS variables,
- minify HTML/CSS if selected,
- package folder and create ZIP.
- Post-export: show summary (files included, size, warnings), and provide open-folder button.
- Checklist dev:
- ensure consistent pathing (relative paths) so exported site runs when hosted statically.
- include meta comment with templateId and templateVersion for traceability.
- fail export if blocking preflight issues remain unless force override with explicit UX.
Project states and local persistence (state machine for dev/PM)
- New → Draft: initial created project, autosave enabled.
- Editing: user makes changes; dirty flag true.
- Validated: ran preflight with zero blockers; can export.
- Warning: preflight yields warnings but no blockers.
- Blocked: preflight yields blockers; export disabled unless force override.
- Exported: final ZIP produced; project.savedExportPoints[] appended with metadata.
- Archived: user marks project archived; app may compress or read-only it.
Checklist to hand to dev/PM as behavior flow diagram (sequence checkpoints)
- On New Project create files and initial manifest snapshot.
- On Template Select validate template manifest; copy template package.
- On Content Change update model, autosave, run lightweight validation (required presence, image metadata).
- On Preview request ensure render uses same pipeline as Export.
- On Validate run full preflight; categorize issues and block/present remediation.
- On Export check export options, run asset pipeline (generate srcset), render final HTML, minify, package zip, write export log.
- On Save/Close ensure state persisted and user warned if unsaved changes.
Dùng checklist trên, developer và PM sẽ có một sơ đồ hành vi chi tiết để kiểm tra mỗi bước implement, các ràng buộc validation cần xử lý, và trạng thái dự án lưu local để đảm bảo trải nghiệm marketer ổn định và tránh lỗi export.
Yêu cầu chức năng bắt buộc (MVP)
Mục tiêu chức năng của MVP là cung cấp một ứng dụng PC cho phép marketer hoặc nhân viên content nhanh dựng và xuất sale page tĩnh từ nội dung có sẵn, với trải nghiệm chọn template theo chủ đề, tùy chỉnh nhanh, preview responsive và xuất HTML/CSS/asset sạch. Dưới đây là danh sách tính năng bắt buộc, kèm các ràng buộc vận hành và validation bắt buộc trước khi cho phép xuất.
- Nhập nội dung có sẵn (input)
- Hỗ trợ import:
- JSON: import file project.json theo schema template.
- CSV: map cột sang fields (mapping UI).
- Markdown: import block markdown cho vùng rich text.
- Paste: dán văn bản hoặc HTML; app sẽ sanitize và chuyển về markdown/HTML an toàn.
- Lưu ý UX: cho phép preview mapping trước khi áp data vào template.
- Chọn template theo chủ đề
- Thư viện template có phân nhóm chủ đề (Sức khỏe, Làm đẹp).
- Template package phải chứa manifest (template.json) với các trường tối thiểu: templateId, version, requiredFields, themeVariables, mediaRequirements.
- Chức năng preview template trước khi dùng; khi chọn, app clone template vào dự án.
- Tùy chỉnh nhanh (editing)
- Thay hình: drag-and-drop vào vùng ảnh, upload từ file system; ảnh được lưu vào thư mục project assets.
- Thay văn bản: hai chế độ
- Form fields có cấu trúc (title, subtitle, list items).
- Inline editing trên preview cho các vùng ngắn.
- Màu và font: palette theme với tối thiểu 6 biến màu và 2 font (heading, body); thay đổi cập nhật trực tiếp preview bằng CSS variables.
- Undo/redo và autosave local.
- Preview responsive
- Preview 3 kích thước tối thiểu: desktop, tablet, mobile.
- Preview phản ánh đúng HTML/CSS xuất ra (đừng chỉ là mock). Preview dùng cùng pipeline render như export.
- Hiển thị cảnh báo visual nếu một trường tràn (long text) hoặc ảnh không đúng aspect ratio.
- Lưu project local
- Project lưu dưới dạng folder: project.json (versioned), /assets/, /templates/active/.
- Autosave định kỳ và save as exportable .zip project.
- Cho phép open recent projects and import project.zip.
- Export HTML/CSS tĩnh
- Tạo bộ file index.html + css/ + assets/ + optional js/ theo cấu trúc relative paths.
- Hai chế độ export:
- Light: fonts/images tham chiếu CDN bên ngoài (nhỏ gọn).
- Self-contained: tất cả assets và font được đóng gói.
- Export phải đảm bảo:
- index.html chứa meta viewport, charset.
- images xuất kèm srcset + sizes và width/height attributes.
- css scope bằng root class để tránh override global.
- Gói kết quả thành ZIP để người dùng download hoặc lưu.
- Form lead capture
- Trình tạo form đơn giản kèm các field cơ bản và honeypot chống spam.
- Submit options cấu hình: webhook URL, Zapier webhook, Formspree/Getform endpoints. App xuất snippet form action phù hợp.
- Form handler không mặc định gửi data ra internet; mọi tích hợp network phải do user cấu hình rõ ràng.
- Manifest template và quản lý template
- Mỗi template phải có manifest hợp lệ.
- Chức năng import/export template dưới dạng zip package.
- Hỗ trợ versioning template (templateId + version) để trace khi export.
- Validation pre-export (preflight)
- Bắt buộc chạy preflight trước export; preflight phân loại vấn đề: BLOCKER, WARNING, INFO.
- Kiểm tra tối thiểu:
- Schema validation (JSON Schema / ajv) với requiredFields.
- Media validation: file tồn tại, kích thước tối thiểu, aspect ratio phù hợp.
- HTML sanitization cho rich text.
- Kiểm tra form action hợp lệ (valid URL) nếu form tồn tại.
- Kiểm tra rằng index.html không phụ thuộc runtime backend để hiển thị nội dung chính.
- BLOCKER phải được sửa trước export trừ khi user explicit override qua confirm.
- Mapping import/export dữ liệu và báo lỗi rõ ràng
- Khi import JSON/CSV, app hiển thị bản đồ mapping (CSV column → template field).
- Khi có mismatch, app liệt kê các field missing và gợi ý sửa hoặc map thủ công.
- Asset/media handling cơ bản
- Khi upload ảnh, app lưu bản gốc và tạo preview nhanh; app auto-generate metadata: intrinsic width/height.
- Quy tắc mặc định cho prototype: chặn upload file > 10 MB; cảnh báo nếu ảnh nhỏ hơn threshold cho hero (ví dụ width < 800 px).
- App phải lưu metadata srcset widths chuẩn: 480, 768, 1200, 1920.
- Các ràng buộc API nội bộ và hạn chế cần tuân thủ
- Tên IPC / internal API calls phải định danh rõ và không blocking UI: ví dụ ipc.render.invoke(“project:save”), ipc.render.invoke(“export:run”).
- Mọi call nặng (image batch optimize, zip create) phải chạy off-main thread hoặc process riêng, trả progress qua events.
- Không tự động upload assets hoặc dữ liệu người dùng ra mạng mà không có opt-in rõ ràng; network calls phải qua API được bật bởi user.
- Hạn mức hiệu năng prototype:
- Single export job should not block UI; cung cấp progress + cancel.
- Giới hạn mặc định file assets per project để tránh OOM trên máy yếu; ví dụ warn khi assets total > 200 MB.
- Không vượt quyền filesystem ngoài workspace project dir trừ khi user explicit chọn folder khi export.
- Các validation UX và báo cáo lỗi
- Mọi lỗi validation phải hiển thị rõ ràng: field path, loại lỗi, gợi ý khắc phục.
- Lưu log export (timestamp, templateId, templateVersion, preflight result) trong project để audit.
Phần này là những yêu cầu tối thiểu bắt buộc để prototype vận hành an toàn và hữu dụng. Các điều chỉnh sâu hơn (ví dụ chuyển đổi ảnh chất lượng cao offline, tích hợp CMS/CRM tự động) là các feature mở rộng và phải tôn trọng các ràng buộc API nội bộ nêu trên.
Đề xuất kiến trúc kỹ thuật tổng quan
Mục tiêu kiến trúc: một ứng dụng PC cross-platform cho phép marketer chọn template, nhập nội dung, preview responsive và xuất HTML/CSS tĩnh. Dưới đây là so sánh hai lựa chọn ưu tiên Electron và Tauri theo các tầng chính, quy ước IPC/command, và đề xuất mặc định cho prototype.
- Tầng UI renderer
- Electron: renderer là SPA (React hoặc Vue 3) chạy trong Chromium embedded. Lợi: dev speed rất cao, đầy đủ toolchain (Vite/webpack), dễ tích hợp WYSIWYG editors (TipTap), state libs (Zustand/Pinia). Hạn chế: tiêu thụ RAM, package lớn.
- Tauri: frontend cũng là SPA tương tự; chạy trên WebView hệ thống. Lợi: binary nhỏ hơn, startup nhanh hơn. Hạn chế: cần cấu hình thêm để gọi API native, đôi khi debug phức tạp hơn.
- Template engine layer
- Đề xuất: Handlebars (Node) cho prototype. Rationale: syntax đơn giản, partials/helpers rõ ràng, dễ compile server-side/local.
- Triển khai:
- Electron: render template bằng Handlebars trong main process hoặc dedicated worker process để tránh blocking UI.
- Tauri: render template có thể thực hiện trong frontend JS (client-side compile) hoặc bằng command Rust gọi runtime Node script; khuyến nghị render bằng thư viện JS trên client để giữ pipeline đơn giản.
- Media processing
- Yêu cầu: preview nhanh, export chất lượng, tạo srcset/webp.
- Kiến trúc hybrid:
- Immediate client-side preprocessing để show preview: browser canvas / Pica / browser-image-compression. Tạo preview và minimal srcset metadata.
- Background native optimization cho export: sharp (libvips) chạy trong native context.
- Electron: dễ dàng tích hợp sharp trực tiếp (Node native module) trong main process hoặc worker. Tiện cho batch optimize và tạo AVIF/WebP.
- Tauri: không có sharp JS; để đạt chất lượng tương đương cần viết command Rust dùng libvips bindings hoặc spawn và bundle binary (sharp CLI or cwebp). Nếu team không có Rust skill, Tauri làm chậm dev.
- File IO và project storage
- Cần read/write project JSON + assets folder + zip export.
- Electron: dùng fs Node trực tiếp trong main process; renderer giao tiếp qua contextBridge IPC để tránh NodeIntegration bật trực tiếp.
- Tauri: dùng tauri::api::fs hoặc viết command Rust; cần cấu hình allowlist cho file APIs. Lợi ích: security-by-default; nhược điểm: phải thêm code Rust nếu file ops phức tạp.
- Export pipeline
- Luồng đề xuất cho prototype:
- UI builds project JSON and assets references.
- Validate schema (ajv) in renderer.
- Send “export:prepare” IPC to native layer with data + assets metadata.
- Native layer runs image optimization tasks if requested, compiles Handlebars templates to index.html, injects CSS variables, generates srcset and sizes attributes, minifies assets (cssnano/terser/html-minifier), writes files to export folder.
- Native layer zips folder and returns path via IPC.
- IPC naming conventions: “project:save”, “project:load”, “export:prepare”, “media:optimize”, “export:zip” for clarity.
- IPC / command boundaries
- Nguyên tắc: keep heavy, filesystem, and native-processing out of renderer.
- Renderer responsibilities: UI, preview rendering (client-side compile for speed), input validation, minor image preview transforms.
- Native responsibilities: durable storage, batch image transforms, final template render for export (ensures deterministic output), minify/zip and long tasks with progress events.
- Progress reporting: native emits events “export:progress” and “media:progress” so UI shows progress and allows cancel.
- Trade-offs chính
- Tốc độ phát triển
- Electron win nếu team JS/TS muốn prototype nhanh, tận dụng sharp, npm libs.
- Tauri win nếu team chấp nhận Rust và ưu tiên gói nhẹ.
- Kích thước binary
- Electron lớn hơn (Chromium bundled). Nếu gói nhẹ quan trọng sớm, Tauri có lợi.
- Xử lý ảnh native
- Electron thuận lợi: sharp sẵn, ít rào cản kỹ thuật.
- Tauri khả thi nhưng cần kỹ năng Rust hoặc bundling của native binaries, làm tăng dev time.
- Đề xuất mặc định cho prototype
- Chọn Electron nếu bạn cần prototype nhanh, muốn tích hợp sharp để đảm bảo chất lượng ảnh export và có dev JS sẵn. Kiến trúc: React + Vite renderer, Handlebars rendering trong main worker, sharp cho media, fs trong main process, IPC qua contextBridge.
- Nếu bạn bắt buộc phải có binary nhỏ từ đầu và có Rust resource, chọn Tauri và thiết kế render pipeline tương tự nhưng chuẩn bị viết command Rust cho image pipeline hoặc plan dùng cloud optimization khi export.
- Một vài quy ước kỹ thuật cần tuân thủ
- Template package structure: template.json (manifest), layout.hbs, partials/, assets/, styles.css.
- Template manifest phải khai báo requiredPaths, mediaConstraints (minWidth, aspectRatio), themeVariables.
- Export must include width/height attributes, srcset, sizes, and aspect-ratio CSS on containers to avoid CLS.
- Long-running native jobs must be cancellable and return progress via IPC.
Kết luận kiến trúc: cho prototype nội bộ với yêu cầu xử lý ảnh native và tốc độ dev cao, Electron là lựa chọn pragmatic. Nếu mục tiêu là build sản phẩm nhẹ, an toàn hơn cho release, chuyển sang Tauri sau khi prototype ổn định là đường đi hợp lý.
Stack frontend và công nghệ UI đề xuất
Mục tiêu phần này là chỉ rõ một stack frontend thực tế để bạn nhanh triển khai prototype editor/preview cho sale page, đồng thời tổ chức mã sao cho dễ port sang Tauri sau này. Mình nêu lựa chọn ưu tiên, thư viện WYSIWYG/Markdown, CSS strategy, testing visual và pattern tổ chức renderer.
Lựa chọn framework và tooling cơ bản
- React + Vite (ưu tiên cho prototype): nhanh, hệ sinh thái phong phú, dễ tích hợp tiptap và react-markdown. Vite cho HMR rất nhanh khi dev UI. Nếu đội bạn thích Vue thì Vue 3 + Vite là thay thế ngang năng lực.
- Language: TypeScript để có schema-safe state và props, giúp mapping JSON → template an toàn hơn.
State management và data flow
- Dùng state nhẹ: Zustand hoặc useReducer + Context. Tránh Redux nặng. Mô hình đơn giản:
- projectStore: metadata + content JSON + assets list
- uiStore: preview viewport, selected field, dirty flags
- Luồng dữ liệu: editor updates → projectStore → preview component thực hiện client-side render của template (Handlbars compiled) để show WYSIWYG.
Editor WYSIWYG / rich text / markdown
- Rich text: TipTap (ProseMirror-based) cho inline editing, block controls, paste handling. TipTap có plugin ecosystem thuận tiện cho sanitization.
- Markdown: react-markdown + rehype/remark plugins cho sanitize và render. Lưu Markdown trong JSON cho các block dài.
- Kết hợp: dùng cả hai. Ví dụ: short copy inline editable trên canvas với TipTap; article block cho markdown.
Template preview và rendering
- Client-side preview: compile Handlebars templates in-memory for instant preview. Điều này giúp preview không cần native layer và dễ test visual.
- Final export: run same Handlebars render in native layer (Electron main hoặc Tauri command) để đảm bảo deterministic output. Không rely chỉ vào client render.
CSS / design system
- Hai lựa chọn hợp lệ:
- Tailwind CSS: nhanh khi xây components, nhưng production build cần purge cẩn thận. Phù hợp nếu bạn muốn nhiều biến thể layout nhanh.
- CSS Modules / SCSS + design tokens: phù hợp nếu muốn CSS scoped rõ ràng và dễ export sạch.
- Pattern đề xuất: template CSS scoped dưới root class, ví dụ .sp-template-<id> để tránh tên lớp toàn cục. Theme variables lưu dưới :root hoặc injected inline khi export:
- –brand-1, –accent, –text, –container-max
- Always include utility CSS rules to prevent paste-borne inline styles breaking layout: img { max-width:100%; height:auto; object-fit:cover } and .rich-text { word-break:break-word; white-space:normal }.
Media handling in renderer
- Renderer chỉ làm preview-thumbnails và light client-side resize using canvas / Pica. Không thực hiện heavy batch convert ở renderer.
- Metadata: whenever user drops an image, record intrinsic width/height and create a preview variant. Store these in projectStore so export can use them.
Organizing renderer code for easy port to Tauri
- Keep renderer pure web: avoid requiring Node APIs or electron modules in UI code.
- Abstraction boundary:
- Define an IPC service interface (TypeScript types) with methods like saveProject, loadProject, optimizeImages, exportProject. Implement one adapter for Electron (via contextBridge IPC) and a stub/mock adapter for web dev.
- Example: src/services/nativeApi.ts exports interface NativeApi { saveProject(p): Promise; exportProject(opts): Promise<string>; } and implementations src/adapters/electronNative.ts, src/adapters/mockNative.ts.
- Build with Vite in SPA mode so same bundle can be loaded by Electron or served to Tauri WebView.
- Avoid direct imports of node-only libs in UI. All filesystem and heavy lifting go through the nativeApi adapter.
Visual testing and QA
- Use Playwright or Puppeteer for automated visual regression. Workflow:
- For each template and sample JSON, render pages in headless Chromium at multiple viewports and capture screenshots.
- Compare with baseline via pixel-diff (or Playwright snapshots). Integrate into CI to catch layout regressions from content changes.
- Unit / integration:
- Test Handlebars helpers and render pipeline with Jest and jsdom.
- Test TipTap content sanitization and paste scenarios.
Developer ergonomics and build
- Local dev: run Vite dev server for renderer and start main process in dev mode. Expose mock native adapter for fast UI-only dev.
- Production build: Vite build outputs static assets. For Electron, copy these into app resources. For Tauri, use same build artifacts and bundle with Rust binary.
Tóm tắt hành động kỹ thuật ngắn
- Start with React + Vite + TypeScript.
- Use TipTap for inline editing, react-markdown cho markdown.
- Scope CSS per-template, prefer CSS Modules or Tailwind with careful purge.
- Implement a nativeApi adapter boundary to isolate Node/native calls, để dễ port sang Tauri.
- Add Playwright visual tests per-template as part of CI.
Phần này cung cấp đủ để bạn hoặc đội dev bắt tay scaffolding renderer, đồng thời giữ mã dễ chuyển sang Tauri khi cần.
Template engine và mapping nội dung
Mình chọn Handlebars làm engine ưu tiên cho prototype vì cú pháp rõ ràng, hỗ trợ partials và helpers dễ, và có runtime Node để render cả ở preview lẫn export. Nếu bạn thích Liquid vì compatibility với một số CMS, ý tưởng mapping tương tự áp được. Phần này mô tả cách tổ chức templates/partials, manifest template.json, quy tắc mapping JSON → template path, helper cần thiết, cách render local/server-side, và cách scope CSS bằng root class name. Cuối phần mình giao một manifest mẫu và ví dụ mapping thực tế.
- Cấu trúc template và partials
- Mỗi template là một folder độc lập:
- template.json – metadata và schema (manifest)
- layout.hbs – entry layout, dùng partials
- partials/ – hero.hbs, benefits.hbs, testimonial.hbs, footer.hbs, …
- assets/css/ – styles.css (scoped bằng root class)
- assets/img/ – sample images, thumbnails
- Partial nhỏ, single-responsibility: mỗi partial chỉ render data theo schema đã định. Điều này cho phép tái dùng giữa templates.
- manifest: template.json (mẫu hoàn chỉnh)
- manifest định nghĩa:
- id, name, category, version
- requiredFields: list JSON paths bắt buộc
- fields: mô tả các field để UI sinh form input
- themeVariables: danh sách biến màu/font có thể override
- preview: thumbnail path, default viewport
- Ví dụ manifest hoàn chỉnh:
{
"id": "health-hero-01",
"name": "Clinical Offer - Hero Right Form",
"category": "suc-khoe",
"version": "1.0.0",
"requiredFields": [
"meta.title",
"hero.title",
"hero.image",
"hero.cta[0].label"
],
"fields": {
"meta.title": { "type": "text", "label": "Title" },
"hero.title": { "type": "text", "label": "Hero title" },
"hero.subtitle": { "type": "text", "label": "Hero subtitle" },
"hero.image": { "type": "image", "label": "Hero image", "aspectRatio": "16:9", "minWidth": 1200 },
"hero.cta": { "type": "list", "itemSchema": { "label": "text", "href": "url" } },
"testimonials": { "type": "list", "itemSchema": { "name": "text", "text": "html", "photo": "image" } }
},
"themeVariables": {
"brandColor": "#D6336C",
"accentColor": "#F59E0B",
"fontHeading": "Inter, sans-serif"
},
"preview": {
"thumbnail": "assets/preview.png",
"viewport": "desktop"
}
}
- Quy tắc mapping JSON → template path
- JSON data dùng path dot notation tương ứng manifest:
- Primitive fields: meta.title → {{meta.title}}
- Arrays: benefits[] → iterate with #each: {{#each benefits}}{{> benefitPartial this}}{{/each}}
- Optional fields: partials phải support conditional rendering: {{#if hero.subtitle}}<p>{{hero.subtitle}}</p>{{/if}}
- Mapping rules cụ thể:
- Template chỉ đọc các paths được khai báo trong manifest.fields hoặc dùng safe helpers để tránh undefined output.
- Nếu field là list, manifest có itemSchema; UI chỉ cho phép nhập theo itemSchema để tránh type mismatch.
- Luôn lưu metadata ảnh: original width/height và generated srcset entries để export tạo attribute width/height và srcset.
- Helpers cần thiết (Handlebars)
- imageSrcset(context) – trả về <picture> hoặc srcset HTML dựa trên metadata image object (webp + fallback). Example usage: {{{imageSrcset hero.image “hero”}}}
- safeHtml(htmlString) – sanitize và trả raw HTML an toàn. Example: {{{safeHtml testimonial.text}}}
- formatPrice(value, currency) – format tiền tệ cho phần product templates.
- ifEqual / unlessEqual – so sánh strings để lựa variant.
- loopWithIndex – helper trả index trong each nếu cần.
- registerHelpers khi khởi tạo engine trước render preview/export.
- Cách render – client-side preview và server-side / local export
- Client-side preview (fast, non-blocking)
- Compile template in-memory with Handlebars.compile(layout).
- Use same helpers but for image processing preview only use generated thumbnails.
- Preview should not perform heavy image re-encoding. Use metadata to show correct aspect-ratio and placeholder variants.
- Local export (deterministic final output)
- Run render in Node context (Electron main or build script) to produce full HTML string.
- During export, replace theme variables into CSS, inject critical CSS if needed, build picture elements using full srcset files that were generated by image pipeline.
- Validate manifest.requiredFields before render; fail export with explicit messages if missing.
- Scope CSS bằng root class name
- Mỗi template root element có class duy nhất, pattern: sp-template-<id> e.g. <body class=”sp-template-health-hero-01″>
- CSS trong assets/styles.css viết dưới scope:
- .sp-template-health-hero-01 h1 { … }
- .sp-template-health-hero-01 .hero { … }
- Khi export, replace :root variables per template theme:
- :root { –brand-color: #D6336C; –accent: #F59E0B; }
- Kết quả: template CSS không va chạm giữa templates và tránh global selectors như h1 { }.
- Ví dụ mapping ngắn: JSON → Handlebars usage
- JSON snippet:
{
"hero": {
"title": "Tư vấn chuyên khoa trực tuyến",
"subtitle": "Gặp bác sĩ trong 24h",
"image": { "path":"assets/img/hero.jpg", "width":2400, "height":1350, "srcset":["assets/img/hero-480.webp","assets/img/hero-1200.webp"] },
"cta": [{ "label":"Đăng ký", "href":"#form" }]
}
}
- layout.hbs snippet usage:
<body class="sp-template-health-hero-01">
<header class="hero">
<div class="hero-text">
<h1>{{hero.title}}</h1>
{{#if hero.subtitle}}<p>{{hero.subtitle}}</p>{{/if}}
{{#each hero.cta}}
<a class="btn btn-primary" href="{{href}}">{{label}}</a>
{{/each}}
</div>
<div class="hero-media">
{{{imageSrcset hero.image "hero"}}}
</div>
</header>
{{> testimonialsPartial testimonials=testimonials}}
</body>
Tóm tắt thực thi nhanh
- Kiểm tra manifest.requiredFields trước mọi render.
- Dùng partials nhỏ, helpers chuẩn để tránh logic trong template.
- Preview nhẹ, export chạy render trên Node/Electron main để đảm bảo srcset/width/height được inject.
- Scope CSS bằng root class name để tránh specificity và inline styles từ content phá layout.
Thiết kế hệ thống template và component tái dùng
Mục tiêu: xây một hệ thống template/partial/component có thể tái dùng giữa nhiều mẫu sale page, dễ quản lý, và tạo được per-template CSS bundles nhỏ để giảm CSS footprint. Mình mô tả phân lớp template, design tokens, CSS variables, theme variants, component API (props JSON), danh sách partial chuẩn, và cách quản lý CSS để build per-template bundles. Các ví dụ là mẫu hoàn chỉnh bạn có thể dùng ngay.
- Nguyên tắc phân lớp template
- Layout (page shell): cấu trúc HTML chung của trang, chứa head/meta, header, footer, và vị trí đặt sections.
- Sections: khối lớn trên trang, ví dụ hero, features, testimonials, faq, cta. Sections ghép từ các partials nhỏ.
- Partials (components): unit nhỏ, single responsibility, tái dùng across sections. Ví dụ: hero-media, hero-content, benefit-card, testimonial-card, faq-item, cta-bar.
- Tách rõ: layout dùng sections; sections dùng partials. Khi render, Handlebars/engine chỉ ghép layout + sections cần thiết.
- Danh sách partial chuẩn (số lượng và tên đề xuất)
- header.hbs
- footer.hbs
- hero/content.hbs
- hero/media.hbs
- benefits/list.hbs
- benefit/item.hbs
- testimonials/list.hbs
- testimonial/item.hbs
- faq/list.hbs
- faq/item.hbs
- cta/bar.hbs
- gallery/carousel.hbs
- product/feature.hbs
- disclaimer/block.hbs
Tổng 14 partials là chuẩn để dựng 8 mẫu minh họa; mở rộng thêm partial khi cần.
- Design tokens và CSS variables
- Lưu tokens ở tập tin JSON global (design-tokens.json) và export vào CSS custom properties khi build template.
- Token nhóm chính:
- colors: brand-1, brand-2, accent, text, bg
- spacing: space-1..space-6
- typography: font-base, font-heading, size-h1..p
- radii, shadows, breakpoints
- Khi export template, inject :root hoặc body.root-class { –brand-1: #… } để override per-template.
Ví dụ tokens (mẫu hoàn chỉnh):
{
"colors": {
"brand": "#D6336C",
"accent": "#F59E0B",
"text": "#1F2937",
"bg": "#FFFFFF"
},
"typography": {
"fontHeading": "Inter, sans-serif",
"fontBody": "Noto Sans, sans-serif",
"h1Size": "2rem",
"bodySize": "1rem"
},
"spacing": {
"sm": "8px",
"md": "16px",
"lg": "24px"
}
}
- Theme variants
- Mỗi template có một or vài theme variants (ví dụ light, dark, promo). Biến thể là bộ giá trị token thay đổi. UI cho phép chọn variant; engine inject tương ứng.
- Implement bằng CSS variables. Khi user đổi màu nhanh, app chỉ cập nhật variables mà không rebuild CSS.
- Component API (props JSON)
- Mỗi partial định nghĩa schema props để UI tự động sinh form. Đây là ví dụ hoàn chỉnh cho hero partial:
{
"component": "hero",
"props": {
"title": { "type": "text", "required": true },
"subtitle": { "type": "text", "required": false },
"image": { "type": "image", "required": true, "aspectRatio": "16:9", "minWidth": 1200 },
"cta": {
"type": "list",
"itemSchema": {
"label": { "type": "text", "required": true },
"href": { "type": "url", "required": true },
"variant": { "type": "enum", "options": ["primary","ghost"], "default": "primary" }
}
},
"layoutVariant": { "type": "enum", "options": ["media-left","media-right","full-width"], "default": "media-right" }
}
}
- UI đọc schema để validate input, show image aspect guidelines, và map JSON vào template path (hero.title, hero.image…).
- Pattern tái dùng để giảm CSS footprint
- Component-scoped CSS: mỗi partial có file CSS riêng, tên hóa theo component, ví dụ hero.css. Không include style global.
- Root scoping: mỗi template export gắn class root .sp-template-<id>. Mọi selector bắt đầu bằng .sp-template-<id> để tránh global collision.
- Build per-template bundle: khi export, detect partials dùng trong template, concat chỉ CSS của các partials đó + base reset + token vars. Không ship toàn bộ component library.
- Avoid global utilities: hạn chế utility classes toàn cục; thay vì ship Tailwind compile toàn bộ, dùng tiny utility subset hoặc generate per-template utilities.
- CSS modularization: keep component rules minimal and rely on CSS variables for visual differences. Ví dụ benefit-card chỉ chứa layout and spacing; colors come from variables.
- Kỹ thuật tạo per-template CSS bundles
- Đặt mỗi component CSS ở src/components/<name>/styles.css.
- At export time:
- Parse template manifest to list used partials.
- Concatenate base.css + tokens.css + used partials’ styles.
- Run PostCSS pipeline: autoprefixer, cssnano (safe settings).
- Optionally run PurgeCSS against rendered HTML to strip unused rules, with safelist patterns for dynamic classes.
- Store resulting styles as assets/css/styles.css referenced by index.html.
- Ví dụ hoàn chỉnh nhỏ: hero partial + usage
- Handlebars snippet:
<section class="hero {{layoutVariant}}" aria-label="Hero">
<div class="hero-content">
<h1>{{hero.title}}</h1>
{{#if hero.subtitle}}<p class="hero-sub">{{hero.subtitle}}</p>{{/if}}
{{#each hero.cta}}<a class="btn btn-{{variant}}" href="{{href}}">{{label}}</a>{{/each}}
</div>
<div class="hero-media">
{{{imageSrcset hero.image "hero"}}}
</div>
</section>
- CSS (component-scoped excerpt):
.sp-template-health-hero-01 .hero { display:flex; gap:var(--space-lg); align-items:center; padding:var(--space-lg); }
.sp-template-health-hero-01 .hero.media-right { flex-direction:row; }
.sp-template-health-hero-01 .hero-media img { width:100%; height:auto; object-fit:cover; display:block; }
- Khi export, only this CSS plus base/token files are bundled.
- Quy tắc vận hành và kiểm soát
- Mỗi partial phải: a) có props JSON schema, b) có CSS riêng, c) có test snapshot. Điều này cho phép build per-template bundles chính xác.
- Purge/run-on-render: purge CSS only after rendering HTML with actual data to avoid removing dynamic classes.
- Safelist prefixes: is-, has-, btn- để bảo toàn lớp động.
- Giữ helper imageSrcset dùng metadata do pipeline ảnh tạo để injection width/height và srcset tránh CLS.
Kết luận tóm tắt hành động
- Triển khai template folder pattern, partial CSS files, token system, và export pipeline that picks only used partial CSS. Dùng schema-driven props để UI validate và mapping dữ liệu. Giải pháp này vừa tái dùng component vừa hạn chế CSS footprint cho mỗi template xuất.
Bộ 8 mẫu minh họa (4 sức khỏe, 4 làm đẹp)
Dưới đây là 8 mẫu template minh họa dành cho prototype. Mỗi mục nêu mục đích, cấu trúc section chính, danh sách biến cần thay (title, hero, benefits, testimonials, CTA, disclaimers, v.v.), và lưu ý compliance cụ thể cho ngành sức khỏe / làm đẹp.
- Clinical Offer – Tư vấn chuyên khoa
- Mục đích: thu lead cho buổi tư vấn y tế trực tuyến hoặc đặt lịch khám.
- Sections: head/meta, hero (text + form), credibility badges, benefits/features, doctor profiles, testimonials, FAQ, footer.
- Biến cần thay: meta.title, hero.title, hero.subtitle, hero.image, hero.formFields, badges[], benefits[], doctors[], testimonials[], ctaPrimary, footer.links, disclaimer.text.
- Compliance: bắt buộc trường disclaimer.visible và disclaimer.text mặc định “Không phải lời khuyên y tế”; cấm nội dung khẳng định chữa khỏi; form thu dữ liệu sức khỏe phải kèm checkbox đồng ý xử lý dữ liệu.
- Wellness Program – Chương trình chăm sóc dài hạn
- Mục đích: đăng ký chương trình coaching/chăm sóc sức khỏe.
- Sections: hero (full-bleed), program timeline, package cards, pricing + CTA, social proof, FAQ, signup modal.
- Biến: program.title, timeline[], package[].title, price, benefits[], testimonials[], cta.label, cta.href, disclaimer.
- Compliance: không cho phép minh chứng lâm sàng không kiểm chứng; bắt show disclaimer và chỗ để upload chứng nhận chuyên gia nếu yêu cầu.
- Supplement Product – Sản phẩm bổ sung
- Mục đích: single-product page cho viên uống/ thực phẩm chức năng.
- Sections: hero (product gallery + buy CTA), product highlights, ingredients, how-it-works, scientific notes, before/after (optional), testimonials, FAQ, footer.
- Biến: product.title, gallery[], ingredients[], benefits[], dosage, researchLinks[], testimonials[], ctaBuy.
- Compliance: luôn hiển thị disclaimer về tuyên bố sức khỏe; nếu có claims, gắn nguồn tham chiếu; cấm copy text dạng “chữa bệnh” nếu không có chứng cứ pháp lý.
- Clinic Event – Workshop / Sự kiện sức khỏe
- Mục đích: đăng ký tham gia sự kiện / hội thảo.
- Sections: hero with countdown, speakers, schedule, ticket tiers, location/map, testimonials, register form, footer.
- Biến: event.title, date, countdown.enabled, speakers[], schedule[], tickets[], ctaRegister, disclaimer.event.
- Compliance: nếu quảng cáo liên quan can thiệp y tế, yêu cầu thông tin ràng buộc về độ tuổi/điều kiện tham gia; thêm field consent nếu thu dữ liệu sức khỏe.
- Skincare Product Launch – Ra mắt sản phẩm chăm sóc da
- Mục đích: bán sản phẩm mỹ phẩm, nhấn visual và công thức.
- Sections: hero carousel, product features, ingredients spotlight, routine steps, before/after gallery, testimonials, CTA voucher, footer.
- Biến: product.title, hero.images[], features[], ingredients[], routine[], beforeAfter[], testimonials[], promoCode, cta.label.
- Compliance: trước/sau phải kèm xác nhận consent; cấm ngôn từ implying medical treatment; cung cấp phần “Lưu ý” cho phản ứng phụ.
- Salon Service – Đặt lịch dịch vụ làm đẹp
- Mục đích: đặt lịch cho salon/nghệ nhân; hiển thị portfolio.
- Sections: hero + booking widget, service list, price table, gallery, team, reviews, booking CTA.
- Biến: salonName, hero.image, services[], prices[], gallery[], team[], testimonials[], bookingLink.
- Compliance: hiển thị thông tin chứng chỉ nhân viên nếu claim chuyên môn; giới hạn ngôn từ tránh hứa hẹn kết quả y tế.
- Cosmetic Procedure Info – Thủ thuật thẩm mỹ thông tin + lead capture
- Mục đích: cung cấp thông tin thủ thuật và thu lead tư vấn.
- Sections: hero + risk panel, procedure overview, before/after slider, patient stories, FAQ, contact form, mandatory disclaimer.
- Biến: procedure.title, riskSummary, benefitsList, beforeAfterPairs[], patientTestimonials[], ctaConsult, disclaimer.risk.
- Compliance: bắt buộc block “risk” hiển thị; yêu cầu đồng ý trước khi tải hình trước/sau; rõ ràng không được quảng cáo chữa bệnh.
- Beauty Course – Khóa học make-up / chăm sóc
- Mục đích: bán khóa học, hiển thị chương trình học và giảng viên.
- Sections: hero (video preview), curriculum accordion, instructor bios, testimonials, pricing tiers, enroll CTA, FAQ.
- Biến: course.title, promoVideo, modules[], instructors[], testimonials[], pricing[], ctaEnroll.
- Compliance: nếu dùng hình mẫu khách hàng, đảm bảo quyền sử dụng ảnh và không quảng cáo kết quả y tế.
Ghi chú dùng chung cho tất cả mẫu
- Mọi template ngành sức khỏe/ thẩm mỹ phải có trường disclaimer cấu hình bắt buộc và vùng upload chứng nhận/nguồn tham khảo.
- Template manifest cần khai báo requiredFields và media.requirements (aspectRatio, minWidth) để tránh lỗi responsive khi xuất.
- Ứng dụng phải cảnh báo nếu văn bản chứa claim y tế bằng rule-based keyword scan trước khi cho phép export ở chế độ “publish”.
Mẫu dữ liệu đầu vào và JSON Schema mẫu
Dưới đây là một JSON mẫu hoàn chỉnh dùng cho một template sale page. Đây là bản điền sẵn để bạn có thể dán vào editor hoặc làm sample data cho rendering, export và kiểm tra preflight.
{
"meta": {
"title": "Khỏe Đẹp Tự Tin - Chương trình 6 tuần",
"slug": "khoe-dep-6-tuan",
"description": "Chương trình 6 tuần giúp cải thiện dinh dưỡng và làn da. Đăng ký nhận tư vấn miễn phí.",
"author": "Clinic A",
"locale": "vi",
"theme": {
"brandColor": "#D6336C",
"accentColor": "#F59E0B",
"fontHeading": "Inter",
"fontBody": "Noto Sans"
}
},
"hero": {
"title": "Làm chủ sức khỏe - đẹp từ bên trong",
"subtitle": "Chương trình 6 tuần với chuyên gia dinh dưỡng và thẩm mỹ",
"image": {
"src": "assets/img/hero-1600.jpg",
"width": 1600,
"height": 900,
"srcset": [
{"src":"assets/img/hero-480.webp","w":480},
{"src":"assets/img/hero-1024.webp","w":1024},
{"src":"assets/img/hero-1600.webp","w":1600}
],
"alt": "Hình minh họa chương trình"
},
"cta": [
{"label": "Đăng ký tư vấn", "type": "primary", "href": "#signup"}
]
},
"benefits": [
{"title": "Kế hoạch ăn uống cá nhân", "desc": "Lộ trình dinh dưỡng cá nhân hóa cho từng thể trạng", "icon": "assets/icons/meal.svg"},
{"title": "Chăm sóc da chuyên sâu", "desc": "Quy trình chăm sóc da theo chuẩn bác sĩ da liễu", "icon": "assets/icons/skin.svg"},
{"title": "Hỗ trợ trực tiếp", "desc": "Tư vấn online trong suốt 6 tuần", "icon": "assets/icons/support.svg"}
],
"testimonials": [
{"name": "Lan H.", "text": "Da mình cải thiện rõ sau 4 tuần.", "photo": "assets/img/t1.jpg"},
{"name": "Minh T.", "text": "Chế độ ăn dễ thực hiện, hiệu quả.", "photo": "assets/img/t2.jpg"}
],
"faq": [
{"q": "Chương trình kéo dài bao lâu?", "a": "6 tuần, gồm 3 buổi tư vấn trực tiếp và hỗ trợ online."},
{"q": "Có hoàn tiền không?", "a": "Xem chính sách hoàn tiền trong phần điều khoản."}
],
"ctaBlocks": [
{"text": "Đăng ký ngay để nhận ưu đãi 20%", "button": {"label": "Đăng ký", "href": "#signup"}}
],
"footer": {
"company": "Clinic A",
"links": [{"label": "Chính sách", "href": "/policy"}]
},
"settings": {
"layoutVariant": "hero-left",
"formAction": "https://hooks.example.com/collect",
"requireDisclaimer": true,
"disclaimer": "Nội dung chỉ mang tính tham khảo, không thay thế tư vấn y tế chuyên môn."
}
}
Hướng dẫn viết JSON Schema cho template (AJV)
- Mục đích: validate dữ liệu người dùng trước khi bind vào template và trước khi export.
- Nguyên tắc: mỗi template kèm schema riêng. Schema bao gồm required fields theo manifest.requiredFields (xem phần manifest bên dưới). Dùng ajv để validate; bật strictTypes.
Ví dụ JSON Schema (rút gọn, Handlebars template “standard” schema):
{
"$id": "https://example.com/schemas/salepage.v1.json",
"type": "object",
"required": ["meta", "hero", "settings"],
"properties": {
"meta": {
"type": "object",
"required": ["title", "slug"],
"properties": {
"title": {"type": "string"},
"slug": {"type": "string", "pattern": "^[a-z0-9\\-]+$"},
"description": {"type": "string"},
"author": {"type": "string"},
"locale": {"type": "string"}
},
"additionalProperties": true
},
"hero": {
"type": "object",
"required": ["title", "image"],
"properties": {
"title": {"type": "string"},
"subtitle": {"type": "string"},
"image": {
"type": "object",
"required": ["src", "width", "height"],
"properties": {
"src": {"type": "string"},
"width": {"type": "integer", "minimum": 1},
"height": {"type": "integer", "minimum": 1},
"alt": {"type": "string"},
"srcset": {
"type": "array",
"items": {
"type": "object",
"required": ["src", "w"],
"properties": {"src": {"type": "string"}, "w": {"type": "integer"}}
}
}
}
},
"cta": {
"type": "array",
"items": {
"type": "object",
"required": ["label"],
"properties": {"label": {"type": "string"}, "href": {"type": "string"}}
}
}
}
},
"benefits": {
"type": "array",
"items": {
"type": "object",
"required": ["title", "desc"],
"properties": {"title": {"type": "string"}, "desc": {"type": "string"}, "icon": {"type": "string"}}
}
},
"testimonials": {
"type": "array",
"items": {
"type": "object",
"required": ["name", "text"],
"properties": {"name": {"type": "string"}, "text": {"type": "string"}, "photo": {"type": "string"}}
}
},
"faq": {
"type": "array",
"items": {"type": "object", "required": ["q", "a"], "properties": {"q": {"type": "string"}, "a": {"type": "string"}}}
},
"ctaBlocks": {
"type": "array",
"items": {"type": "object", "required": ["text", "button"], "properties": {"text": {"type": "string"}, "button": {"type": "object"}}}
},
"settings": {
"type": "object",
"required": ["layoutVariant", "formAction", "requireDisclaimer"],
"properties": {
"layoutVariant": {"type": "string"},
"formAction": {"type": "string"},
"requireDisclaimer": {"type": "boolean"},
"disclaimer": {"type": "string"}
}
}
},
"additionalProperties": false
}
Ví dụ validate bằng ajv (Node)
const Ajv = require("ajv");
const ajv = new Ajv({allErrors: true, strict: true});
const schema = require("./salepage.v1.json");
const data = require("./sample-data.json");
const validate = ajv.compile(schema);
const ok = validate(data);
if (!ok) {
console.error("Validation errors:", validate.errors);
} else {
console.log("Data is valid");
}
Gợi ý xử lý lỗi validate
- Nếu thiếu required field: báo chính xác JSON path (ajv.errors cung cấp instancePath). Dùng thông báo rõ ràng trong UI: field path, expected type, sample value.
- Nếu additionalProperties: cho phép extraFields: true chỉ khi template manifest cho phép mở rộng.
manifest.requiredFields để preflight check
- Mỗi template kèm một manifest JSON nhỏ để preflight. Ví dụ minimal manifest:
{
"templateId": "health-hero-01",
"version": "1.0.0",
"title": "Clinical Offer",
"category": "health",
"requiredFields": [
"meta.title",
"meta.slug",
"hero.title",
"hero.image.src",
"hero.image.width",
"hero.image.height",
"settings.formAction",
"settings.requireDisclaimer"
],
"media": {
"hero.image": {"aspectRatio": "16:9", "minWidth": 1200}
}
}
Preflight logic (kết hợp schema + manifest)
- Run AJV schema validate. Nếu fail, show errors and block export.
- Check manifest.requiredFields: ensure each JSON path exists and non-empty. Nếu any missing, mark as blocking.
- Check media rules: validate image width/height and aspectRatio. Nếu image too small, warn or block depending manifest policy.
- Generate preflight report JSON with lists: blockingIssues[], warnings[]; present to user before export.
Kết luận thực hành nhanh
- Sử dụng per-template JSON Schema + manifest.requiredFields là cơ sở chắc để phát hiện mismatch trước render/export.
- Luôn validate image metadata (width/height/srcset) và lưu metadata khi user import ảnh.
- Trong UI, hiển thị lỗi preflight rõ ràng với path, lý do và ví dụ sửa.
Giao diện chọn và quản lý template, import/export
Mục tiêu giao diện: cho phép bạn duyệt, xem trước, cài, xuất và quản lý templates theo chủ đề nhanh chóng; cho phép admin quản lý phiên bản, phân quyền và nhập/xuất dưới dạng package (.zip) chuẩn để chia sẻ hoặc backup.
Giao diện chính
- Bar trên cùng: search, filter theo chủ đề (Sức khỏe, Làm đẹp, Tất cả), chế độ grid/list toggle.
- Thư viện template (grid): mỗi card có thumbnail, tiêu đề, tags, version, badges (public / private / draft).
- Action trên card: Use / Preview / Duplicate / More (menu).
- Preview modal: hiển thị full-size preview ở 3 viewport (desktop / tablet / mobile) có toggle, live sample data switch (sample A / sample B), nút “Use this template” và nút “Open template editor” nếu bạn có quyền.
- Template detail panel (slide-over): metadata (id, version, author, changelog), required fields summary, manifest validation status, last updated, permissions.
Preview modal behavior
- Pre-render HTML using current sample data to show exact output; cho phép bật overlay hiển thị JSON path khi hover một vùng để liên kết nhanh tới field editor.
- Cho phép download preview as static HTML zip for quick review.
- Khi preview phát hiện blocking preflight issues, hiển thị tag cảnh báo kèm link tới preflight report.
Quy trình import / export template
- Import:
- UI: nút Import template ZIP, drag-and-drop area, validation summary.
- App unzip package to temp, validate manifest.json + schema, check for required partials/assets. Nếu lỗi, show detailed report và reject.
- On success, prompt chọn category và quyền mặc định (private/public/team).
- Export:
- UI: menu Export -> options: Export Package (.zip) or Export Minimal (partials + manifest).
- Package bao gồm template folder, manifest.json, partials, assets, README.md, changelog.
- Support exporting a template snapshot tied to a specific version tag.
Versioning và lifecycle
- Template manifest includes templateId, version (semver), changelog, supported schemaVersion.
- UI supports: publish new version, rollback to earlier version, view diff between versions (partials diff).
- When user imports a template with same templateId but higher version, show upgrade dialog: preview changes, migrate samples if migration script present.
- Templates can be forked to create variant without affecting original.
Permissions and roles
- Roles: Viewer, Editor, Template Admin.
- Viewer: browse, preview, use template for projects but cannot edit or export template package.
- Editor: create projects from templates, customize per-project, suggest template changes (creates draft).
- Template Admin: import/export templates, publish versions, set category, manage ACL, approve suggested edits.
- UI: per-template ACL panel to add/remove users or teams, set default project sharing settings.
Các hành động UI cần có (quick list)
- Browse by category/tag/search
- Preview modal with viewport switcher and JSON-path overlay
- Use template -> create project from template
- Duplicate template -> fork
- Edit template -> open template editor (partials/CSS/manifest)
- Import template ZIP -> validate -> register
- Export template ZIP -> choose includeAssets? includeSamples?
- Publish version / Rollback / View changelog
- Set ACL and download audit log
File structure cho template package (bắt buộc, máy đọc)
- templates/<templateId>/ | title: Clinical Offer | version: 1.0.0 | category: health
- templates/<templateId>/manifest.json | required: true | schemaVersion: 1
- templates/<templateId>/layout.hbs | type: layout | required: true
- templates/<templateId>/partials/header.hbs | type: partial
- templates/<templateId>/partials/hero.hbs | type: partial
- templates/<templateId>/partials/benefits.hbs | type: partial
- templates/<templateId>/styles/styles.css | type: stylesheet | tokens: variables.css
- templates/<templateId>/assets/logo.svg | type: asset
- templates/<templateId>/assets/img/preview-thumbnail.png | type: asset
- templates/<templateId>/samples/sample-data.v1.json | type: sample | schemaVersion: 1
- templates/<templateId>/migrations/ (optional) | scripts to upgrade older sample shapes
- templates/<templateId>/README.md | license, usage, complianceNotes
Ghi chú ngắn
- Manifest phải liệt kê requiredFields và media rules để preflight nhanh.
- Import/Export phải validate manifest + schema trước khi chấp nhận.
- Quyền quản lý template nằm riêng so với quyền chỉnh dự án, để marketing dùng template mà không sửa template gốc.
Trình soạn thảo nội dung và validation
Mục tiêu phần này: mô tả chi tiết các chế độ soạn thảo (inline editing, form fields, markdown), cách tổ chức UX để marketer thao tác nhanh, và hệ thống validation thời gian thực cần có để đảm bảo templates nhận nội dung có sẵn chạy an toàn trên layout responsive. Đồng thời nêu cách logging mapping các trường thiếu và trả về báo cáo rõ ràng trước khi export.
- Các chế độ soạn thảo và khi dùng
- Inline editing (WYSIWYG nhẹ)
- Dùng cho các vùng ngắn: hero title, subtitle, CTA label, card title. Triển khai bằng contentEditable hoặc TipTap/ProseMirror.
- UX: double-click để edit, Enter commit, Esc hủy; inline toolbar nhỏ (bold/italic/link) xuất hiện trên selection.
- Ưu: trực quan, nhanh cho marketer. Hạn chế: không dùng cho block markdown phức tạp.
- Form fields (structured editor)
- Bảng bên phải liệt kê tất cả field theo schema template (text, richtext, list, image, url, boolean).
- Dùng khi cần nhập nhiều mục có cấu trúc (benefits[], testimonials[]). Hỗ trợ bulk paste từ CSV/Excel cho list.
- UX: focus jumps to preview vùng tương ứng khi click field; có nút “populate sample” để test layout.
- Markdown + preview
- Dùng cho bài dài, disclaimers, long copy. Lưu markdown trong JSON và render sanitized HTML cho preview.
- Live preview cạnh nhau; hỗ trợ basic remark plugins cho links và image embedding.
- Chế độ kết hợp
- Cho phép marketer chuyển đổi: ví dụ double-click hero text mở form field tương ứng để chỉnh chi tiết (giữ single source of truth).
- UX tiết kiệm thao tác cho marketer
- Inline edits auto-sync về JSON data + autosave (debounce 800ms). Undo/redo per-project.
- Smart paste: khi paste text có nhiều dòng vào single-line field, app nhắc “Bạn có muốn dán vào block nhiều dòng?” để chuyển qua markdown.
- Drag-and-drop image vào vùng preview để upload và auto-generate srcset variants.
- Quick actions: replace all images, swap color palette, apply sample data.
- Field linking: map một field JSON vào nhiều vùng (ví dụ meta.title và hero.title) với toggle “sync”.
- Inline validation hints: hiển thị icon cảnh báo ngay trên vùng nếu lỗi; click mở panel mô tả lỗi và hướng sửa.
- Validation thời gian thực cần có
Thực thi validation ở hai lớp: client-side nhanh cho UX; preflight toàn diện trước export. Các loại kiểm tra:
A. Required fields
- Kiểm tra theo template manifest.requiredFields (list of JSON paths).
- Hiển thị warning khi missing; blocking export nếu field vòng “required” là blocking.
- Ví dụ: manifest.json có “requiredFields”: [“hero.title”,”hero.image”,”cta[0].label”]
B. Image dimensions / aspect ratio / file size
- Khi user upload: read intrinsic width/height và file size.
- Rules example:
- Hero: minWidth = 1200 px, aspect = 16:9 preferred. Nếu width < 800 px: warning; nếu width < 600 px: blocking for hero.
- Thumbnails: minWidth = 400 px.
- Max file size before optimize: 5 MB; recommend compress < 300 KB for hero mobile.
- UX: nếu image không đạt, hiển thị badge trên preview với suggested crop button, or auto-crop to aspect ratio with preview.
- Technical: ensure exported HTML includes width/height attributes and aspect-ratio CSS fallback.
C. URL format
- Validate using robust regex or URL constructor. Example quick check (concept):
try { new URL(value); } catch(e) { invalid }
- Additionally check for supported schemes (http, https, mailto, tel). Warn if link missing protocol.
D. Length limits and text patterns
- Meta title length <= 70 chars; meta description <= 160 chars (show counter).
- Section titles: recommend <= 60 chars; card text <= 200 chars with live truncation preview.
- Detect long unbreakable strings (e.g., long base64 or long slug with no spaces) and insert soft-wrap or warn.
- For lists, enforce max items per template variant (e.g., benefits max 6) or layout will break.
E. Rich text sanitization and disallowed inline styles
- Sanitize pasted HTML to remove style attributes, script tags, style tags, and potentially dangerous HTML. Use DOMPurify with allowed tags set.
- Normalize inline styles: remove px font-sizes inserted by MS Word paste.
F. Accessibility and contrast quick checks
- For chosen palette, compute color contrast ratio and warn if below 4.5:1 for body text.
- Validation flow and blocking policy
- Real-time layer: quick checks on edit, non-blocking warnings except for clearly required or corrupt assets.
- Preflight layer (before export): run full validation and produce a report:
- Blocking issues: missing required fields, hero image below min_width, links invalid.
- Non-blocking issues: color contrast low, long text, images large.
- Export blocked if any blocking issues exist. Provide “export anyway” only for admin role with explicit confirmation and audit log.
- Logging mapping missing fields and báo cáo trước export
- Khi render template, engine instrumentation records which JSON paths were accessed and their values. Nếu path undefined or null, add to mapping report.
- Report format (JSON example for UI and audit):
{
"templateId": "clinic-hero",
"version": "1.0.0",
"checkedAt": "2026-07-16T10:00:00Z",
"missingFields": [
{"path":"hero.image","reason":"missing","severity":"blocking"},
{"path":"testimonials[0].photo","reason":"missing","severity":"warning"}
],
"typeMismatches": [
{"path":"benefits","expected":"array","actual":"string"}
],
"mediaWarnings": [
{"path":"hero.image","issue":"width=640 < minWidth=1200","suggestedAction":"replace or run Optimize images"}
],
"advice": [
"Meta description longer than 160 chars: consider shortening for SEO",
"Color contrast low for CTA: consider darker text"
]
}
- UI shows report grouped by blocking/non-blocking, with direct buttons to jump to field, auto-fix suggestions (crop, compress, replace), and “download report” for audit.
- Technical implementation notes (practical)
- Use JSON Schema (ajv) per template for structural validation. Example fragment for hero:
{
"type":"object",
"properties": {
"hero": {
"type":"object",
"properties": {
"title":{"type":"string"},
"image":{"type":"string","format":"uri"}
},
"required":["title","image"]
}
},
"required":["hero"]
}
- On render, produce AST-path extraction (from Handlebars parse) to know which paths template references; compare to provided JSON to catch unmapped fields early.
- For image processing: immediate client-side generate quick srcset via canvas for preview; background worker (sharp) for production-quality variants on export.
- For URL validation use try/catch with URL; for pattern checks use configurable regex list stored in template manifest.
- UX patterns for error handling
- Inline badges with short sentence and link to fix.
- Preflight modal with summary count and expand/collapse per issue class.
- Suggested one-click fixes: “replace hero image”, “auto-resize and convert to webp”, “truncate text to 140 chars”.
- Audit log: record export attempts that were blocked and user actions taken.
Kết luận ngắn gọn về phạm vi kỹ thuật: triển khai editor phải kết hợp structured form + inline WYSIWYG + markdown với autosave và immediate validation; trước export chạy preflight dùng JSON Schema + AST-driven mapping để tìm missing/path mismatches; logging trả về JSON report có severity để marketer và dev dễ xử lý.
Trình soạn thảo nội dung và validation
Mục tiêu phần này: mô tả chi tiết các chế độ soạn thảo (inline editing, form fields, markdown), cách tổ chức UX để marketer thao tác nhanh, và hệ thống validation thời gian thực cần có để đảm bảo templates nhận nội dung có sẵn chạy an toàn trên layout responsive. Đồng thời nêu cách logging mapping các trường thiếu và trả về báo cáo rõ ràng trước khi export.
- Các chế độ soạn thảo và khi dùng
- Inline editing (WYSIWYG nhẹ)
- Dùng cho vùng ngắn: hero title, subtitle, CTA label, card title.
- Triển khai bằng contentEditable hoặc TipTap/ProseMirror để có undo/redo và toolbar nhỏ.
- UX: double-click để edit, Enter commit, Esc bỏ thay đổi; toolbar xuất hiện trên selection với bold/italic/link.
- Ưu/nhược: trực quan, nhanh cho marketer. Hạn chế với nội dung dài hoặc paste từ Word.
- Form fields (structured editor)
- Panel bên phải liệt kê tất cả field theo schema template (text, richtext, list, image, url, boolean).
- Dùng khi cần nhập nhiều mục có cấu trúc như benefits[], testimonials[]. Hỗ trợ bulk paste từ CSV/Excel cho list.
- UX: click field focus vùng tương ứng trên preview; có nút “populate sample” để test layout.
- Markdown + preview
- Dùng cho bài dài, disclaimers, long copy. Lưu markdown trong JSON; render sanitized HTML cho preview.
- Live preview cạnh nhau; react-markdown hoặc unified/remark cho parsing, hỗ trợ image embedding.
- Chế độ kết hợp
- Cho phép chuyển giữa inline và form. Ví dụ double-click hero text mở form field để chỉnh chi tiết. Mọi thay đổi đồng bộ vào cùng một nguồn dữ liệu (project JSON).
- UX tiết kiệm thao tác cho marketer
- Autosave debounce (ví dụ 800 ms) và undo/redo per project.
- Smart paste: nếu paste nhiều dòng vào single-line field, app gợi ý chuyển về markdown hoặc form list.
- Drag-and-drop ảnh trực tiếp lên preview; ảnh được copy vào project assets và tạo derivative nhanh cho preview.
- Quick actions: apply sample data, swap palette, replace all images.
- Field linking: cho phép sync giữa meta.title và hero.title với toggle “sync”.
- Inline validation badges: cảnh báo ngay trên vùng nếu lỗi; click dẫn tới panel chi tiết.
- Validation thời gian thực cần có
Hai lớp: client-side nhanh cho UX, và preflight toàn diện trước export.
A. Required fields
- Dùng manifest.requiredFields trong template để kiểm tra presence. Missing required được đánh severity blocking.
- Ví dụ manifest:
{
"requiredFields": ["hero.title","hero.image","cta[0].label"]
}
B. Image rules
- Khi upload, đọc intrinsic width/height + file size.
- Quy tắc gợi ý:
- Hero: minWidth 1200 px, aspect 16:9 preferred; nếu width < 800 px → warning; width < 600 px → blocking.
- Thumbnails: minWidth 400 px.
- Max upload raw file: 5 MB.
- UX: nếu ảnh không đạt, show badge với action “auto-crop” hoặc “optimize now”.
C. URL validation
- Validate bằng constructor URL để tránh regex rườm rà.
function isValidUrl(value) {
try {
const u = new URL(value);
return ['http:', 'https:', 'mailto:', 'tel:'].includes(u.protocol);
} catch (e) {
return false;
}
}
D. Length and content patterns
- Meta title <= 70 chars; meta description <= 160 chars with counter.
- Section titles recommend <= 60 chars; card text <= 200 chars. Hiển thị preview truncation.
- Detect long unbreakable strings and warn to insert soft-breaks.
E. Rich text sanitization
- Dùng DOMPurify hoặc tương đương để remove style attributes, script tags, style tags. Cho phép whitelist tags cần thiết.
- Bình thường remove inline style px để tránh override CSS template.
F. Accessibility quick checks
- Contrast ratio check cho palette; nếu < 4.5:1 với body text hiển thị cảnh báo.
- Kiểm tra alt attributes cho ảnh.
- Validation flow và blocking policy
- Real-time: hiển thị warnings không chặn thao tác, trừ các lỗi rõ ràng như missing required hoặc media corrupted.
- Preflight (trước export): chạy full validation, tạo báo cáo phân loại blocking / non-blocking. Export bị chặn nếu có blocking issues. Có tùy chọn “Export anyway” chỉ cho admin với audit log.
- Logging mapping missing fields và báo cáo trước export
- Khi render preview/export, runtime ghi lại các JSON path được truy cập và kết quả. Nếu path undefined/null thì đưa vào report.
- Report có cấu trúc machine-readable để UI hiển thị và lưu audit. Ví dụ:
{
"templateId": "clinic-hero",
"version": "1.0.0",
"checkedAt": "2026-07-16T10:00:00Z",
"missingFields": [
{"path":"hero.image","reason":"missing","severity":"blocking"},
{"path":"testimonials[0].photo","reason":"missing","severity":"warning"}
],
"typeMismatches": [
{"path":"benefits","expected":"array","actual":"string"}
],
"mediaWarnings": [
{"path":"hero.image","issue":"width=640 < minWidth=1200","suggestedAction":"replace or Optimize images"}
],
"advice": [
"Meta description longer than 160 chars",
"CTA contrast low vs background"
]
}
- UI actions: click item → focus trực tiếp vào trường tương ứng trong editor; cung cấp one-click fixes khi có thể (auto-resize, compress, crop, truncate).
- Kỹ thuật triển khai thực tế
- Structural validation: duy trì JSON Schema per-template và validate bằng ajv trước render.
- AST-driven mapping: parse Handlebars template để thu danh sách paths tham chiếu. So sánh với data để catch missing keys trước render runtime.
- Image pipeline: quick client-side derivatives cho preview (canvas / Pica), production-quality variants bằng sharp trong background worker trước export.
- Proxy instrumentation: dùng Proxy như kiểm tra bổ sung trong dev mode nhưng không phụ thuộc hoàn toàn vào nó. AST + schema mới là primary detection.
- Quy ước UX cho lỗi và cảnh báo
- Đánh dấu rõ severity: blocking (màu đỏ), recommended (màu vàng), info (xanh).
- Không hide cảnh báo; bắt user confirm fix hoặc acknowledge trước export blocked.
- Lưu audit log của mọi export attempt bị block và mọi lần override export.
Kết luận ngắn: editor phải kết hợp inline + structured + markdown với autosave, immediate validation, và preflight kiểm tra dựa trên JSON Schema cộng AST-driven mapping. Report mapping phải machine-readable để dev và marketer sửa nhanh, và pipeline media phải phối hợp với validation để tránh lỗi responsive do ảnh.
Responsive design system và breakpoints + lỗi thường gặp
Mục tiêu phần này: cung cấp một hệ thống responsive thực dụng cho sale page, quy ước breakpoint, mẫu grid/flex cho các section thường dùng, quy tắc ảnh để tránh CLS, liệt kê lỗi responsive hay gặp khi nhét content có sẵn và cách phòng tránh, kèm checklist test responsive trước khi export.
- Breakpoints đề xuất (dễ áp dụng và phổ biến)
- xs (mobile small): 320 – 480 px
- sm (mobile): 481 – 767 px
- md (tablet): 768 – 991 px
- lg (desktop small): 992 – 1199 px
- xl (desktop): 1200 px trở lên
Ghi chú: đây là khung khởi điểm. templates có thể tinh chỉnh theo thiết kế, nhưng giữ các ngưỡng này giúp nhất quán.
- Grid / flex patterns cho các section chính
- Hero
- Desktop: 2-column 60/40 hoặc 50/50 – text + image. Dùng CSS grid: grid-template-columns: minmax(0, 1fr) minmax(0, 1fr).
- Tablet: vẫn 2-column nhưng chuyển thành 1-column nếu image quá cao.
- Mobile: stacked – image dưới hoặc trên tùy UX. Giữ CTA luôn hiển thị cao trong viewport.
- Kỹ thuật: use align-items: center; gap: 24px; image container min-height bằng CSS variable theo breakpoint.
- Features / Benefits
- Desktop: grid 3 columns (repeat(3, 1fr)).
- Tablet: grid 2 columns.
- Mobile: 1 column.
- Kỹ thuật: use grid-auto-rows: 1fr cho cards cùng chiều cao; card nội bộ dùng flex column để footer CTA luôn bottom-aligned.
- Testimonials
- Desktop: 3-column card grid hoặc centered carousel.
- Tablet: 2-column grid hoặc carousel showing 2.
- Mobile: single card carousel / stacked list.
- Kỹ thuật: nếu dùng carousel, đảm bảo kích thước và aria controls, và fallback stacked list nếu JS absent.
- Quy tắc aspect-ratio và <img> attributes để tránh CLS (practices)
- Luôn chèn intrinsic width và height attributes trên <img> nếu biết kích thước gốc. Nếu không, áp dụng CSS aspect-ratio trên container, ví dụ .hero-media { aspect-ratio: 16 / 9; } và img { width:100%; height:100%; object-fit:cover; display:block; }.
- Sử dụng <picture> + srcset + sizes để cho browser chọn kích thước phù hợp. Ví dụ srcset=”img-480.webp 480w, img-1200.webp 1200w” sizes=”(max-width:767px) 100vw, 50vw”.
- Luôn dùng loading=”lazy” cho ảnh không xuất hiện trên first viewport, ngoại trừ hero nếu cần hiển thị ngay.
- Đặt display:block cho <img> để tránh inline baseline gaps.
- Nếu dùng responsive background-image, reserve space bằng một pseudo-element với padding-top theo tỷ lệ để tránh shift.
- Các lỗi responsive thường gặp khi nhét content có sẵn và cách phòng tránh
- Ảnh không có width/height hoặc tỉ lệ khác kỳ vọng
- Hậu quả: hero phình to, CLS cao.
- Khắc phục: khi import ảnh, đọc intrinsic size; auto-generate srcset và aspect-ratio placeholder; warn nếu ảnh nhỏ hơn ngưỡng.
- Rich text paste kèm inline styles
- Hậu quả: override CSS template, phá layout mobile.
- Khắc phục: sanitize HTML, strip style attributes, chuyển paste thành plain text hoặc markdown, có nút “Keep formatting” tùy chọn.
- Long unbreakable strings (URLs, emojis, base64)
- Hậu quả: horizontal overflow.
- Khắc phục: css rule word-break: break-word; overflow-wrap: anywhere; add zero-width-space vào strings nếu cần.
- Fixed heights / absolute positioned elements
- Hậu quả: cắt nội dung hoặc chồng lấp.
- Khắc phục: tránh height:px trên content; dùng min-height / max-height với units tương đối; sử dụng flow layout.
- Inline styles / high specificity từ content
- Hậu quả: template CSS bị ghi đè.
- Khắc phục: namespace toàn bộ template với .sp-<template> root class; dùng CSS variables và !important chỉ ở edge-case; sanitize inline style hoặc scope nó.
- Missing container fallbacks khi component optional
- Hậu quả: khoảng trắng lớn khi testimonials/benefits thiếu.
- Khắc phục: template phải có conditional rendering và CSS fallback cho số lượng phần tử khác nhau.
- Checklist test responsive (phải chạy trước export)
- Viewport check: render và kiểm tra tại 320, 375, 414, 768, 1024, 1366.
- CLS check: measure cumulative layout shift; đảm bảo hero và images có width/height hoặc aspect-ratio.
- Image quality/sizes: verify srcset selects appropriate file; file size cảnh báo cho hero > 300 KB desktop.
- Overflow check: no horizontal scroll, test long words & pasted HTML.
- Forms and CTA: buttons visible above fold on mobile; touch target >= 44px.
- Font loading: font-display: swap; check FOIT/FOUT.
- Accessibility quick checks: alt attributes, logical heading order, contrast >= 4.5:1 cho body text.
- JS-free fallback: kiểm tra page render cơ bản nếu client JS không chạy.
- Export integrity: mở exported index.html local và kiểm tra assets path relative đúng.
Kết luận ngắn: hệ thống responsive hiệu quả dựa trên breakpoints chuẩn, pattern grid linh hoạt, và quy tắc bắt buộc cho ảnh. Khi nhận content có sẵn, tự động hóa chuẩn hóa ảnh và sanitize rich text là chìa khóa để tránh lỗi. Hãy chạy checklist test responsive trước mỗi export để kịp sửa.
Export static HTML/CSS: build pipeline và packaging
Mục tiêu phần này là cung cấp pipeline thực tế để từ template + data sinh ra site tĩnh: index.html + css + assets, tối ưu responsive và nhỏ gọn, cuối cùng đóng gói thành ZIP theo hai chế độ export. Những bước dưới đây là thứ tự thao tác mà bạn hiện thực trong ứng dụng PC (Electron/Tauri) như một command export.
- Tổng quan pipeline (tóm tắt các bước)
- Render template với dữ liệu để tạo HTML tĩnh.
- Inject theme variables (CSS custom properties hoặc biến SCSS) vào stylesheet.
- Sinh responsive srcset cho ảnh và cập nhật markup <picture> / <img> với width/height và sizes.
- Tùy chọn: extract và inline critical CSS cho phần above-the-fold.
- Minify assets: HTML (html-minifier-terser), CSS (cssnano), JS (terser).
- Copy/convert assets (images, fonts, icons) vào thư mục export.
- Tạo zip package hoặc folder export.
- Kiểm tra integrity và báo cáo lỗi/warnings (missing images, undersized hero, broken links).
- Bước chi tiết thực hiện (implementable)
- Render template
- Dùng Handlebars.compile(templateString) hoặc engine bạn chọn. Context = project JSON + theme variables.
- Kết quả: rawHtml string. Lưu temp file render/index.raw.html để pipeline bước sau truy xuất.
- Kiểm tra: đảm bảo head có meta viewport và charset trước khi tiếp tục.
- Inject theme variables
- Thiết kế templates dùng CSS variables: :root { –brand: #… } hoặc inject inline style trong head.
- Lấy theme từ project.meta.theme và generate nhỏ file css/themes.css hoặc inject <style> trong head với custom properties.
- Nếu template dùng SCSS, compile với node-sass/postcss trước khi tiếp tục.
- Generate responsive srcset
- Quy ước: với mỗi ảnh, tạo variants widths = [480, 768, 1200, 1920] nếu ảnh gốc >= các kích thước đó; còn không, tạo theo kích thước gốc.
- Nếu dùng sharp (Electron): run sharp(source).resize(width).toFile(dest).
- Ghi metadata vào project JSON: { “image”: { “src”: “assets/hero-1200.jpg”, “srcset”: [“hero-480.webp 480w”, …], “width”: 1200, “height”: 675 } }.
- Replace markup: use <picture> with <source type=”image/webp” srcset=”…”> and fallback <img src=”…” width=”…” height=”…” loading=”lazy” style=”object-fit:cover;display:block;”>
- Ensure sizes attribute suitable: sizes=”(max-width:767px) 100vw, 50vw”.
- Inline critical CSS (optional)
- Run a critical extractor per-template or use a precomputed critical CSS for each template variant.
- Use penthouse or critical libraries to compute critical CSS for given viewport set, or for prototype, manually author minimal critical CSS (< 14 KB).
- If enabled: inject critical CSS into <head> in a <style> tag; load rest.css with rel=”preload” + onload swap pattern:
<link rel="preload" href="assets/css/styles.css" as="style" onload="this.rel='stylesheet'">
<noscript><link rel="stylesheet" href="assets/css/styles.css"></noscript>
- Minify HTML/CSS/JS
- HTML: html-minifier-terser with options keepClosingSlash true, collapseWhitespace true, removeComments true, minifyJS false/true depending on your in-page scripts.
- CSS: postcss + cssnano with safe options (disable dangerous transforms if you use custom properties extensively).
- JS: terser for any behavioral JS (form handler, accordion). For prototype, avoid bundling heavy frameworks into exported JS.
- Example npm scripts:
"scripts": {
"minify:html": "html-minifier-terser --collapse-whitespace --remove-comments --minify-css true --minify-js true -o export/index.html export/index.raw.html",
"minify:css": "postcss export/assets/css/styles.css -u cssnano -o export/assets/css/styles.min.css",
"minify:js": "terser export/assets/js/main.js -c -m -o export/assets/js/main.min.js"
}
- Copy and convert assets
- Copy generated srcset files and original assets into export/assets/img.
- Fonts: if self-contained export, copy woff2 files into export/assets/fonts and update @font-face urls. For light export, reference Google Fonts link in head.
- SVG icons: inline critical SVGs into HTML when small; keep large SVG files external.
- Create ZIP and manifest
- Build folder structure:
- export/<slug>/index.html
- export/<slug>/assets/css/styles.min.css
- export/<slug>/assets/js/main.min.js
- export/<slug>/assets/img/*
- export/<slug>/assets/fonts/*
- Create manifest.json inside export that includes export mode, templateId, dataVersion, generatedAt, asset list.
- ZIP creation options:
- Node: use archiver package to create zip.
- CLI: on mac/linux use zip -r output.zip folder/.
zip -r mypage.zip export/mypage/
- Integrity checks (final)
- Verify index.html references exist in assets list.
- Check hero image width >= recommended threshold (warn if < 800 px).
- Ensure index.html contains meta viewport.
- Report file sizes and total zip size; warn if self-contained > threshold.
- Hai chế độ export: light và self-contained
- Light (external refs)
- CSS: reference external CDN or Google Fonts.
- Images: reference external URLs (if user used cloud-hosted images) or include optimized small variants only.
- Kích thước package: nhỏ, suitable khi bạn muốn upload to Netlify/Vercel quickly.
- Pros: small ZIP, faster transfer. Cons: depends on external availability.
- Self-contained (all assets)
- All images, fonts, scripts, CSS included locally.
- Inline critical CSS optional to reduce HTTP requests.
- Pros: works fully offline, easy to hand to client. Cons: larger ZIP; be careful with font licensing.
- Implementation tip: allow user to pick mode in export dialog, show estimated sizes for each mode before creating ZIP.
- Hướng dẫn deploy lên Netlify / Vercel / S3 (ngắn, thực tế)
- Netlify
- Kéo thả: unzip ZIP, drag-and-drop folder vào Netlify Sites – Deploys area. Hoặc push to Git and connect repo.
- CLI deploy: install netlify-cli and run:
npx netlify deploy --dir=export/mypage --prod
- Nếu forms: Netlify Forms nhận form action nếu form có data-netlify=”true”; else configure webhook.
- Vercel
- Vercel supports static folder deploy as well:
npx vercel deploy export/mypage --prod
- Vercel auto-detects static site and serves index.html with correct headers. For redirects or headers, include vercel.json.
- S3 + CloudFront
- Upload to S3 bucket configured for static hosting. Example AWS CLI:
aws s3 sync export/mypage/ s3://my-bucket/mypage/ --acl public-read
- Set correct Content-Type and Cache-Control headers. If using CloudFront, invalidate distribution after upload:
aws cloudfront create-invalidation --distribution-id XXXXX --paths "/mypage/*"
- For form handling, configure action to external webhook or Lambda endpoint.
- Cảnh báo và best-practices
- Relative paths: export must use relative paths ./assets/… để site hoạt động khi mở file:// hoặc khi host trên subpath.
- Fonts licenses: do not include paid fonts unless license allows redistribution.
- srcset and width/height: always include width and height or container aspect-ratio to avoid CLS.
- Test exported package by opening export/index.html locally and on a staging host; verify images, forms, and meta tags.
- Show final report to user with warnings: missing required fields, undersized images, large file sizes, and compliance flags if template health-related.
- Quick checklist để tích hợp vào UI export
- [ ] Render success, head contains viewport/charset.
- [ ] Theme variables injected and effective in preview.
- [ ] All image srcset variants generated and present.
- [ ] Critical CSS inlined if option ON.
- [ ] HTML/CSS/JS minified without errors.
- [ ] Assets copied and referenced with relative paths.
- [ ] Manifest.json created with metadata.
- [ ] ZIP created and size reported.
- [ ] Pre-deploy diagnostics passed or user acknowleges warnings.
Kết luận ngắn: pipeline này là flow thực tế để đảm bảo exported sale page tĩnh vừa responsive, vừa nhẹ, và dễ deploy. Trong ứng dụng PC, implement pipeline làm thành task background với progress logs, cho phép cancel và re-run từng bước nếu có lỗi.
SEO cơ bản, performance và accessibility checklist
Mục tiêu: khi bạn xuất một sale page tĩnh từ chương trình, trang phải có metadata chuẩn để search/social, tải nhanh trên mạng di động, và đáp ứng yêu cầu truy cập cơ bản cho người dùng khuyết tật. Dưới đây là checklist thực thi từng bước để tích hợp vào pipeline export và preflight.
- Meta tags tối thiểu
- <meta charset=”utf-8″> và <meta name=”viewport” content=”width=device-width,initial-scale=1″>
- <title> hợp lệ và mô tả ngắn; meta description 50–160 ký tự.
- canonical link khi có nhiều đường dẫn cùng nội dung.
- robots meta khi cần block trang thử nghiệm.
- Open Graph và Twitter Card
- OG tags cơ bản: og:title, og:description, og:image, og:url, og:type.
- Twitter: twitter:card (summary hoặc summarylargeimage), twitter:title, twitter:description, twitter:image.
- Ảnh OG: cung cấp kích thước chuẩn (ví dụ 1200×630) trong assets và tham chiếu trực tiếp. Nếu không có ảnh lớn, tránh để og:image trống.
- Structured data (JSON-LD) — tùy chọn nhưng khuyến nghị
- Hỗ trợ schema.org cơ bản: Organization, Product hoặc Event tùy template.
- Đặt script type=”application/ld+json” trong head với dữ liệu có cấu trúc từ project.meta.
- Không bịa claim y tế trong structured data; nếu là content sức khỏe chỉ dùng Organization/FAQ/LocalBusiness.
- Hình ảnh và loading
- Luôn cung cấp width và height attribute hoặc CSS aspect-ratio cho <img> để giảm CLS.
- Sinh srcset và sizes cho hình lớn. Ví dụ variants 480w, 768w, 1200w, 1920w.
- Dùng <picture> với <source type=”image/webp”> và fallback <img>.
- Thêm loading=”lazy” cho ảnh ngoài above-the-fold; critical hero nên không lazy nếu cần hiển thị ngay.
- Kiểm tra: hero desktop < 300 KB tối ưu; mobile variant < 150 KB nếu có thể.
- Fonts
- Sử dụng font-display: swap cho @font-face để tránh FOIT.
- Nếu self-host font, subset glyphs cho Latin hoặc ngôn ngữ mục tiêu; không inline toàn bộ font trong CSS mặc định.
- Nếu dùng Google Fonts, cân nhắc preload cho font chính: <link rel=”preload” as=”font”>.
- CSS, critical CSS và render-blocking
- Đặt critical CSS inline cho phần above-the-fold, kích thước lý tưởng < 14 KB.
- Load phần CSS còn lại với rel=”preload” → onload swap pattern hoặc tách file CSS chính.
- Giảm render-blocking bằng cách loại bỏ đồng thời các script chặn (defer/async cho JS không cần thiết).
- Minify CSS và loại bỏ CSS không dùng nếu purge an toàn theo quy trình render-before-purge.
- JavaScript tối thiểu
- Xuất page tĩnh cố gắng không phụ thuộc framework client-side nặng. Nếu có script chỉ dùng để xử lý form/accordion, giữ < 20 KB gzipped.
- Defer/async scripts không quan trọng cho initial render.
- Accessibility cơ bản (kiểm tra trước export)
- Ảnh có alt text mô tả; nếu ảnh trang trí, alt=””.
- Các nút và liên kết có accessible name; dùng aria-label khi cần.
- Tiến trình tab đúng, focus states rõ ràng.
- Kiểm tra contrast: text chính ít nhất 4.5:1, large text 3:1.
- Các form có label liên kết với input; thông báo lỗi accessible.
- Kiểm tra với tool tự động (axe-core) và manual spot checks.
- Performance targets cho prototype
- Time to First Byte không thể kiểm soát kỹ từ export static nhưng khuyến nghị host trên CDN.
- Largest Contentful Paint (LCP) mục tiêu: < 2.5s trên mobile thực tế; prototype chấp nhận < 3.5s.
- Cumulative Layout Shift (CLS): < 0.1 với việc nêu rõ width/height hoặc aspect-ratio.
- Total page weight (light export): aim < 500 KB gzipped (không bao gồm fonts lớn); self-contained có thể lên đến 2–3 MB nhưng cần cảnh báo.
- Kiểm tra cuối cùng trước export (preflight)
- Kiểm tra presence của meta tags quan trọng, og image tồn tại, all images have width/height, srcset present.
- Run automated accessibility scan and report top 5 issues.
- Tính toán tổng size export và cảnh báo nếu vượt ngưỡng.
- Ghi lại manifest metadata (templateId, dataVersion, generatedAt) trong export để trace.
Thực hiện những bước này trong pipeline export và đưa thành warnings/errors rõ ràng trong UI để người dùng fix trước khi public.
Form và lead capture integration options
Mục tiêu: đưa form thu lead hoạt động trên trang tĩnh xuất ra từ chương trình, cho phép marketer cấu hình action dễ dàng và đảm bảo dữ liệu gửi đúng định dạng để xử lý bởi hệ thống bên ngoài.
Tùy chọn tích hợp (mỗi mục có mô tả ngắn, pros/cons, khi dùng)
- Webhook trực tiếp
- Mô tả: form gửi POST JSON hoặc form-encoded tới URL do người dùng cấu hình.
- Pros: đơn giản, realtime, không cần bên thứ ba; dễ tích hợp với backend nội bộ.
- Cons: người dùng cần endpoint server; bảo mật phải xử lý (HMAC signature, rate limit).
- Khi dùng: khách hàng có endpoint xử lý lead.
- Zapier / Make (Integromat)
- Mô tả: form action trỏ tới webhook do Zapier/Make cung cấp; Zap/Scenario xử lý và đẩy tiếp vào CRM, email, Google Sheet.
- Pros: không cần dev backend; hỗ trợ nhiều tích hợp sẵn; dễ cho marketer.
- Cons: phụ thuộc dịch vụ bên thứ ba, giới hạn miễn phí, tiềm ẩn latency.
- Khi dùng: muốn nhanh triển khai nhiều tích hợp mà không code.
- Formspree / Getform
- Mô tả: dịch vụ nhận form POST và forward email hoặc webhook.
- Pros: thiết lập nhanh, phù hợp với static sites, thường hỗ trợ spam protection cơ bản.
- Cons: chi phí khi volume lớn, hạn chế tuỳ biến phức tạp.
- Khi dùng: export landing page tĩnh và cần gửi form về email/Slack nhanh.
- Client-side validation + honeypot
- Mô tả: kiểm tra trước khi gửi; thêm field ẩn chống bot (honeypot) và timestamp.
- Pros: giảm spam, cải thiện UX, không phụ thuộc server.
- Cons: không đủ chống bot tinh vi; vẫn cần server-side validation ở endpoint.
- Khi dùng: luôn bật cả với webhook và services ở trên.
- Optional SMTP upload (local send)
- Mô tả: app cho phép cấu hình SMTP và gửi submission trực tiếp từ máy người dùng khi export hoặc qua server-side run.
- Pros: không cần endpoint ngoài, có thể dùng tài khoản email doanh nghiệp.
- Cons: cấu hình phức tạp, deliverability thấp nếu máy cá nhân, cần bảo mật credential.
- Khi dùng: chỉ cho trường hợp đặc biệt khi không có backend.
Cách export form snippet và mẫu payload
- Export cung cấp hai dạng snippet: HTML form + minimal JS for fetch, và JSON schema mô tả trường.
- Ví dụ HTML snippet (POST JSON to webhook):
<form id="leadForm">
<input name="name" required />
<input name="email" type="email" required />
<input name="phone" />
<input type="hidden" name="projectId" value="{{projectId}}">
<div style="display:none"><input name="hp_field" /></div> <!-- honeypot -->
<button type="submit">Gửi</button>
</form>
<script>
document.getElementById('leadForm').addEventListener('submit', async e=>{
e.preventDefault();
const data = Object.fromEntries(new FormData(e.target));
if (data.hp_field) return; // honeypot
await fetch('{{WEBHOOK_URL}}', {method:'POST', headers:{'Content-Type':'application/json'}, body:JSON.stringify(data)});
// show success
});
</script>
- Ví dụ mẫu payload JSON:
{
"projectId": "health-hero-01",
"submittedAt": "2026-07-16T10:00:00Z",
"name": "Nguyen Van A",
"email": "a@example.com",
"phone": "+84123456789",
"utm": {"source":"facebook","campaign":"summer"}
}
Gợi ý bảo mật và vận hành nhanh
- Luôn kèm server-side validation cho mọi endpoint. Với webhook, cung cấp header HMAC để verify nguồn. Với Zapier/Formspree, bật CAPTCHA hoặc honeypot. Trong export UI, cho marketer chọn integration type, nhập endpoint/keys, và export snippet kèm ví dụ payload và hướng dẫn server-side verification.
Testing, QA và visual regression
Mục tiêu: đảm bảo mỗi template xuất ra hoạt động đúng trên các trình duyệt và viewport mục tiêu, không bị regress khi sửa template, và ngăn xuất trang có lỗi responsive, accessibility hoặc asset. Dưới đây là checklist và quy trình QA thực tế để bạn tích hợp vào workflow dev và export.
- Pre-export checklist (kiểm tra cục bộ trước khi cho phép export)
- Schema validation: chạy JSON Schema (ajv) cho data project; block export nếu required field missing.
- Media checks:
- mọi <img> có intrinsic width/height metadata trong project manifest;
- hero images >= 800 px width cảnh báo, < 400 px block export;
- generated srcset entries tồn tại cho các breakpoint.
- Content sanity:
- no unbreakable long-strings trong fields; apply word-break rules or warn;
- rich-text sanitized (no <style> hoặc <script>);
- CTA URLs valid (http(s) or mailto).
- Accessibility quick checks:
- all images have alt text;
- color contrast check for brand colors against body text; warn if < 4.5:1;
- form inputs have labels.
- Export integrity:
- index.html contains meta viewport and charset;
- asset paths are relative and present in export folder;
- form action configured.
- Cross-browser matrix (minimum for prototype)
- Desktop: Chrome latest, Firefox latest, Safari latest, Edge Chromium latest.
- Mobile: iOS Safari latest, Chrome on Android latest.
- If customer targets older browsers, add legacy targets and run separate legacy build.
- Responsive viewport list (for automated and manual checks)
- Mobile small: 320×568
- Mobile medium: 375×812
- Mobile large: 414×896
- Tablet portrait: 768×1024
- Tablet landscape / small desktop: 1024×1366
- Desktop common: 1366×768 and 1920×1080
Use these sizes for screenshot baselines, interactive testing, and Lighthouse runs.
- Visual regression approach
- Recommended stack:
- Playwright for rendering pages and capturing screenshots across viewports and browsers.
- For pixel comparison: Percy if you want hosted diff + UI; or use open-source pixeldiff / pixelmatch for CI-run diffs.
- Workflow:
- On template change branch, generate rendered HTML for canonical sample data and capture baseline screenshots for each viewport.
- Compare against main branch baselines. Fail CI on visual delta exceeding threshold (e.g., 0.5% of pixels).
- If diffs intentional, update baselines via PR with reviewed change.
- Tips:
- Use per-component screenshots (hero, benefits grid) to isolate diffs.
- Store baselines per template variant and per theme to avoid noisy diffs.
- Automated accessibility
- Integrate axe-core:
- run axe-core checks in Playwright tests for each rendered page and report violations.
- Classify violations: critical (must fix), serious (ideally fix), minor (advisory).
- Also automate contrast checks and ensure keyboard navigation works for interactive components.
- Block export or mark template as “needs attention” if critical violations present.
- Unit tests for template rendering
- Tests to include:
- Render template with minimal valid JSON returns non-empty HTML and no exceptions.
- Render with optional/missing blocks renders fallback behavior (collapsed section, placeholder).
- Helpers: unit tests for custom Handlebars helpers, verifying output for edge inputs.
- Snapshot tests: lightweight HTML snapshot for structural regressions (not pixel-perfect).
- Tooling: Jest for unit tests; use jsdom or Handlebars compile in Node.
- CI gating rules for template changes
- Protect main branch with required checks:
- Linting and unit test pass.
- Template schema validation passes against sample data.
- Rendering unit tests and snapshot tests pass.
- Visual regression checks pass or have approved baseline updates.
- Accessibility critical violations = fail.
- PR requirements:
- If a template file (layout, partial, css) changed, the PR must include updated sample data and at least one manual review sign-off from a reviewer.
- Changes to template manifest.requiredFields must increment manifest version and include migration notes.
- Manual QA checklist for release
- Walk through responsive preview list, verify no horizontal scroll and CTAs visible without overlap.
- Verify images do not cause CLS: load page with slow network throttling.
- Test forms with configured webhook and third-party providers.
- Check exported zip deploys to a static host and behaves identically to local preview.
- Reporting and developer feedback loop
- Failures in CI should generate:
- screenshot diffs,
- axe violation report with selectors,
- render logs including missing fields and image warnings.
- Require attaching these artifacts to PR for faster debugging.
Thực hiện theo quy trình này sẽ giảm hỏng layout do nội dung có sẵn, bắt regress sớm, và giữ export template luôn có chất lượng đủ dùng cho marketing.
Hướng dẫn triển khai prototype và packaging cho Windows/macOS
Mục tiêu phần này: hướng dẫn từng bước để bạn build prototype desktop (Electron hoặc Tauri), đóng gói installer cho Windows và macOS, tạo artifacts để thử nghiệm nội bộ, ghi chú auto-update, và checklist bản phát hành cho testers. Giả định project dùng frontend SPA (React/Vite hoặc Vue/Vite), Handlebars cho template rendering, và xử lý ảnh bằng sharp (Electron) hoặc pipeline client/Rust (Tauri).
- Chuẩn bị môi trường dev
- Yêu cầu chung:
- Node 16+ (hoặc LTS phù hợp), npm/yarn/pnpm
- Git repo với hai folder chính: src/renderer (UI) và src/main (Electron main hoặc Tauri frontend + Rust backend)
- Cài dev deps (example Node):
npm install
# hoặc
pnpm install
- Quy trình phát triển nhanh cho Electron (dev run)
- Khởi tạo project với Vite + React:
npm init @vitejs/app my-app --template react
cd my-app
npm install
- Thêm Electron skeleton: trong package.json scripts:
"scripts": {
"dev": "concurrently \"vite\" \"wait-on http://localhost:5173 && electron .\"",
"build:renderer": "vite build",
"start": "electron ."
}
- Main process basic (src/main/main.js): mở window và load URL dev server hoặc built file.
- Chạy dev:
npm run dev
- Hot reload: bật HMR cho renderer; restart Electron main on file changes bằng electron-reload hoặc nodemon.
- Export pipeline và render templates trong app
- Thực hiện render Handlebars trong main process hoặc workstation worker để tạo index.html: compile template + inject context JSON + theme CSS.
- Sau render, minify HTML/CSS with html-minifier-terser and cssnano before writing to export folder.
- Generate responsive images via sharp in main process:
// pseudocode
await sharp(input).resize(1920).toFile('assets/hero-1920.webp');
- Packaging Electron với electron-builder (Windows NSIS, macOS dmg)
- Cài electron-builder:
npm install --save-dev electron-builder
- Thêm config tối thiểu vào package.json:
"build": {
"appId": "com.yourcompany.salepage",
"files": ["dist/**", "main.js", "package.json", "templates/**"],
"mac": {
"target": ["dmg"]
},
"win": {
"target": ["nsis"]
}
}
- Build renderer trước, sau đó builder:
npm run build:renderer
npm run build // script chạy electron-builder
- Kết quả: installer .dmg cho macOS và .exe/.msi NSIS cho Windows trong thư mục dist/.
- Tauri alternative (lightweight, requires Rust)
- Cài Rust toolchain và Tauri CLI:
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
cargo install tauri-cli
- Tạo frontend bundle:
npm run build // tạo dist
- Tauri build:
cargo tauri build
- Kết quả: native bundles; nếu cần xử lý ảnh nặng bằng Rust, viết Tauri command sử dụng crates (image, libvips binding) hoặc gọi external binary.
- Deliverables để thử nghiệm nội bộ
- Windows installer (.exe/.msi) và macOS .dmg
- Portable export zip sample: một template xuất HTML/CSS tĩnh với assets sẵn
- Project sample file (.sp-project.json) plus assets để reviewer mở trong app
- Release notes ngắn: build version, nội dung test chính, known issues
- Automated smoke test script (sử dụng Playwright) chạm vào: mở app, load project, render preview, xuất zip
- Auto-update note
- Electron: tích hợp electron-updater + Squirrel/NSIS or GitHub releases. Cấu hình publisher và feed URL. Trong prototype, bật auto-update ở chế độ opt-in cho testers; test bằng release draft trên GitHub.
- Tauri: dùng tauri-updater hoặc host update JSON; requires signed releases on macOS. Với prototype, prefer manual update to avoid notarization steps.
- Checklist release cho testers (pre-release)
- Build artifacts:
- Installer cho Windows và macOS tersedia
- Sample project và sample export zip kèm
- Release notes + checklist test
- QA quick checks:
- Installer chạy và cài app, app mở, không crash first-run
- Mở sample project, all fields hiển thị trong preview
- Thay ảnh hero bằng drag-and-drop, preview phản hồi và tạo srcset
- Export static site: unzip export, mở index.html offline, assets hiển thị, meta viewport có mặt
- Form test: gửi đến webhook mẫu verify nhận payload
- Security & privacy:
- App lưu project local trong folder user documents; không gửi dữ liệu lên mạng mặc định
- Nếu tích hợp auto-update, confirm updates được ký (code signing) hoặc có disclaimer
- Performance / resource:
- Test export speed with 10 images; record time; report if > threshold người dùng chấp nhận
- Testers report template:
- OS/version, installer used, steps to reproduce, expected vs actual, logs (if any), screenshot or screen recording
- Ghi chú build ops ngắn
- Windows signing and macOS notarization not mandatory cho internal test, nhưng cần cho public release.
- Sử dụng CI để produce artifacts: pipeline chạy build renderer, run tests, build installers; attach artifacts for testers.
Các bước trên cung cấp luồng build rõ ràng để bạn triển khai prototype, đóng gói cho Windows/macOS, tạo artifacts thử nghiệm nội bộ và checklist kiểm tra release cho testers.
Security, privacy và lưu trữ local-first
Mục tiêu: app mặc định lưu mọi dự án và media hoàn toàn local, giảm rủi ro rò rỉ dữ liệu, và chỉ cho phép đưa dữ liệu lên cloud sau khi người dùng chủ động bật tính năng và đồng ý. Dưới đây là chính sách vận hành và các biện pháp kỹ thuật cần áp dụng cho prototype.
Nguyên tắc chung
- Local-first by default: tạo project mới thì mọi file, ảnh, JSON project, history đều lưu trong thư mục user (ví dụ Documents/YourApp/projects) và không gửi ra mạng. Không bật sync hay telemetry mặc định.
- Opt-in cloud sync: tính năng đồng bộ cloud phải rõ ràng, có modal xác nhận, hiển thị scope dữ liệu sẽ upload, và yêu cầu người dùng nhập credentials. Không bí mật gửi token hay dữ liệu.
Lưu trữ token và credentials
- Không lưu token plain-text. Nếu app dùng Electron, dùng keychain hệ điều hành (ví dụ Keytar) để lưu token; nếu dùng Tauri, dùng OS credential store via tauri plugin hoặc Rust crate tương đương.
- Khi cần, encrypt token/credential trước khi viết vào disk bằng AES-GCM với key được derive từ OS-provided secret hoặc key stored in keychain. Không hard-code keys trong binary.
- Xóa token khi user logout hoặc revoke sync.
Media và quyền riêng tư
- Không upload ảnh tự động. Khi user thêm ảnh vào project, app chỉ copy ảnh vào thư mục dự án local và thực hiện preprocessing local (preview, generate srcset). Nếu có tùy chọn “Upload for CDN/optimize”, luôn hiển thị checklist gồm: files to upload, destination, chi phí/điều khoản, và checkbox đồng ý.
- Bật cảnh báo bản quyền: khi user import ảnh, hiển thị notice rõ ràng nhớ kiểm tra quyền sử dụng ảnh, và cung cấp checklist: có bản quyền? có consent cho before/after? nếu ảnh từ stock, yêu cầu user dán license id hoặc nguồn. Không tự động mặc định cho phép sử dụng.
Secure IPC và sandboxing
- Electron: tắt NodeIntegration trong renderer. Dùng preload + contextBridge để expose safe API surface. Thiết kế API allowlist: chỉ cho phép các hành động cần thiết từ renderer như readProjectList, saveProject, exportZip, openFileDialog. Validate từng request ở main process, kiểm tra path traversal, whitelist extensions khi ghi file, và sanitize input. Ghi log lỗi cho audit nhưng không log nhạy cảm.
- Tauri: cấu hình allowlist chỉ bật API cần thiết (fs, dialog, shell nếu cần). Viết command Rust nhỏ gọn cho các thao tác file hoặc image processing nặng. Tránh bật toàn bộ quyền native.
Validation, encryption at-rest và backups
- Dữ liệu local có thể được encrypted at-rest tùy chọn: cho phép user bật project-level encryption với passphrase. Khi bật, toàn bộ assets + project JSON được lưu dưới dạng encrypted bundle. Hiển thị rõ cảnh báo về mất passphrase.
- Tạo backup local automatic optional (kept in same device) và cung cấp export encrypted package để chuyển giữa máy.
Logging, telemetry và third-party
- Mặc định không bật telemetry. Nếu cần, làm opt-in rõ ràng và minify logs. Khi tích hợp dịch vụ third-party (CDN, image service), hiện rõ tên nhà cung cấp và chính sách lưu trữ; không lưu token của bên thứ ba nếu không cần.
UI & UX an toàn
- Trong editor, hiển thị badges/warnings khi nội dung chứa thông tin nhạy cảm (ví dụ ảnh before/after) và khi user bật upload. Tránh hành vi tự động gửi hoặc preview live lên dịch vụ bên ngoài.
Những quy tắc này đủ để prototype an toàn: local-first mặc định, token được encrypt/kept in OS keychain khi cần sync, ảnh không upload tự động, cảnh báo bản quyền rõ ràng, và IPC/allowlist được thu hẹp để giảm bề mặt tấn công.
Extensibility: marketplace, plugin helpers, migration và versioning
Mục tiêu: làm cho hệ thống template có thể mở rộng an toàn, cho phép marketplace chia sẻ template, cho phép cài helper bổ sung cho Handlebars, và quản lý version/migration sao cho project cũ vẫn render được. Dưới đây là thiết kế thực dụng để bạn triển khai nhanh.
- Template registry – cấu trúc và manifest
- Mỗi template là folder zip chứa:
- template.json – metadata và schema
- layout.hbs + partials/
- assets/ (css, js, images)
- migrations/ (scripts chuyển đổi data cũ)
- template.json mẫu:
{
"id": "clinic-offer-v1",
"version": "1.0.0",
"title": "Clinic Offer",
"category": "health",
"requiredFields": ["hero.title","hero.image","cta[0].label"],
"schemaVersion": 1,
"compatibility": { "minAppVersion": "0.9.0" },
"author": "template-studio",
"license": "proprietary"
}
- Registry local: SQLite hoặc JSON index trong app data lưu metadata, tags, installedVersion, source (marketplace/local).
- Template marketplace – import/export API
- Export package: zip with template folder structure + manifest signature (HMAC using publisher key). Provide endpoint server-side optional to host packages.
- Import flow in app:
- Validate manifest signature or hash.
- Validate template.json schema against app template manifest schema.
- Run preflight rendering using sample data to detect missing helpers or assets.
- Marketplace API endpoints (server side example):
- GET /templates – list with metadata
- GET /templates/:id/download – package zip
- POST /templates/publish – upload package + metadata
- Client verifies publisher identity and shows changelog and required permissions (e.g., needs custom helper).
- Plugin helpers – custom Handlebars helpers
- Design:
- Helpers are isolated JS modules implementing a small interface: name, version, apiVersion, init(options), safeTemplatesAllowed.
- Discovery: helpers can be bundled into app/plugins/ or installed via marketplace. Manifest for plugin lists allowed templates or global.
- Security:
- In Electron, load helper in a sandboxed worker process or run under VM with limited APIs. Never eval arbitrary code in renderer.
- In Tauri, implement helper as WASM/Rust plugin or run Node microservice.
- API example (pseudo):
- registerHelper({name:”formatPrice”, fn: (value,opts)=>”…”, version:”1.0.0″})
- Backward compatibility: helpers carry apiVersion so template engine can reject incompatible helper versions with clear error.
- Template versioning và migration scripts
- Versioning: use SemVer for template versions. Store template.schemaVersion integer for data schema.
- Migration strategy:
- Keep migration scripts in migrations/ as ordered files named 001-to-002.js etc. Each script receives project JSON and returns transformed JSON.
- On template install/update, run migrations whose target > project.schemaVersion in sequence in a sandboxed process.
- Example migration file signature:
module.exports = async function migrate(data) {
// mutate and return new data
if (data.hero && data.hero.titleV2) {
data.hero.title = data.hero.titleV2;
delete data.hero.titleV2;
}
data.schemaVersion = 2;
return data;
}
- Test and rollback: run migrations on a copy; store before/after snapshot; provide rollback if migration fails.
- Backward compatibility strategy
- Render-time fallback: templates should check fields via helpers like hasValue and provide fallbacks. Registry enforces manifest.requiredFields for blocking exports.
- Compatibility layer: app maintains a mapping table of deprecated fields and common renames to attempt auto-mapping during import.
- CI for template updates: when publishing new template version, run automated render tests against a set of sample projects to detect breaking changes.
Tóm tắt hành động kỹ thuật
- Định nghĩa template.json manifest bắt buộc.
- Hỗ trợ import/export zip với signature.
- Cho phép plugins helpers nhưng chỉ chạy trong sandboxed process.
- Migrations là scripts có versioned ordering, chạy tự động trên copy, có rollback.
- CI kiểm tra rendering across versions để giữ backward compatibility.
Compliance workflow cho nội dung sức khỏe và làm đẹp
Mô tả ngắn: cung cấp một quy trình nhiều lớp để giảm rủi ro vi phạm quảng cáo y tế khi người dùng tạo sale page. Quy trình kết hợp ràng buộc trên template, khối disclaimer bắt buộc, kiểm tra ngôn ngữ theo quy tắc cấu hình được, chế độ xuất draft vs publish, luồng phê duyệt có người kiểm, và hệ thống ghi log/audit cùng UI giúp reviewer thấy rõ cụm từ rủi ro.
- Template-level constraints
- Mỗi template trong nhóm sức khỏe/làm đẹp có manifest khai báo:
- requiredFields: các trường bắt buộc (ví dụ hero.title, disclaimer.text).
- prohibitedFields: danh sách trường không cho phép chứa certain claim fields (ví dụ “cureclaim”, “beforeafter_unverified”).
- contentPolicies: flag bật các kiểm tra cụ thể (e.g., “nomedicalclaims”, “requireconsentfor_images”).
- mediaRules: yêu cầu kích thước, metadata consent checkbox cho before/after images.
- Cơ chế áp dụng: khi user chọn template, app enforce UI controls theo manifest. Nếu template yêu cầu consent cho ảnh trước/sau thì trường upload ảnh kèm trường checkbox bắt buộc; nếu thiếu, export bị block.
- Mandatory disclaimer block
- Mỗi template health-themed có vùng disclaimer bắt buộc hiển thị ở vị trí nổi bật (đầu trang hoặc ngay trước CTA) với nội dung template cung cấp mặc định và cho phép tuỳ chỉnh có giới hạn ký tự.
- App chèn disclaimer cả vào HTML export và metadata JSON; export loại “publish” không cho phép bỏ hoặc ẩn disclaimer.
- Mẫu disclaimer mặc định phải rõ ràng, ví dụ: “Nội dung mang tính tham khảo. Không phải lời khuyên y tế. Vui lòng tham khảo chuyên gia y tế.” Trường hợp cần điều chỉnh theo luật địa phương, manifest có thể chứa biến locale để chọn text phù hợp.
- Rule-based phrase scanner (configurable)
- Cốt lõi: engine scan text fields theo bộ quy tắc configurable gồm:
- keyword lists: danh sách từ/cụm từ cấm hoặc rủi ro (ví dụ “chữa khỏi”, “đảm bảo khỏi”, “không cần thuốc”).
- regex patterns: bắt các cấu trúc như “giảm X% trong Y tuần” hoặc “được chứng minh”.
- contextual rules: kết hợp trường (nếu field = testimonial và chứa “cure” thì higher risk).
- Behaviour:
- mỗi kết quả scan được gán mức rủi ro: low/medium/high và lý do.
- rules có thể được bật/tắt theo template hoặc theo vùng pháp lý (user chọn target country).
- rules lưu cấu hình trong file JSON có versioning; admin có thể cập nhật rule set.
- Hạn chế: đây là lớp cảnh báo tự động, không thay thế phê duyệt con người.
- Publish vs Draft export
- Draft export:
- Dùng cho review nội bộ; không áp dụng block mạnh. Export có watermark “DRAFT” và không được dùng cho chạy quảng cáo.
- Publish export:
- Kiểm tra toàn bộ rules; nếu có high-risk findings hoặc missing required disclaimers thì block export.
- Publish export ghi log vào audit trail và tạo nhiệm vụ phê duyệt nếu cần.
- UX: khi user chọn “Publish”, app hiển thị preflight report tóm tắt issues; xuất sẽ bị chặn cho đến khi các blocking issues được giải quyết hoặc admin override kèm lý do.
- Human-in-the-loop approval flow
- Khi scan tìm thấy medium/high risk hoặc template manifest yêu cầu review:
- Tạo reviewer task trong app: page preview + list highlight cụm từ rủi ro (xem phần UI).
- Reviewer có 3 hành động: Approve, Request changes (commented), Reject.
- Approve có thể kèm điều kiện: e.g., “approve for Vietnam only” nếu có điều kiện địa lý.
- Audit: mọi quyết định lưu với reviewer id, timestamp, reason, và snapshot của nội dung tại thời điểm phê duyệt.
- Logging / audit trail
- Ghi lại:
- tất cả export attempts (user, templateId, exportMode, result).
- kết quả phrase scan (ruleId, matchedText, position).
- reviewer actions (approve/request/reject) với comment.
- media consents (user provided checkbox, file metadata).
- Lưu trữ: log dạng append-only local DB (SQLite) trong app data; option export audit log as CSV/JSON cho compliance team.
- Retention: policy mặc định 180 ngày, cấu hình được.
- UI để highlight risky phrases cho reviewer
- Trong editor preview:
- những cụm từ bị rule đánh dấu sẽ được highlight inline bằng màu theo mức rủi ro (yellow cho medium, red cho high).
- tooltip trên highlight hiển thị rule name + suggested remediation (ví dụ: replace “chữa khỏi” bằng “hỗ trợ cải thiện”).
- sidebar “Compliance Panel” liệt kê tất cả findings, cho phép nhảy tới vị trí text, thêm comment, và tạo task yêu cầu sửa.
- Export preflight report:
- tóm tắt counts by severity, list blocking issues, và direct buttons: Fix in editor / Mark as reviewed with justification (admin only).
Thiết lập mặc định cho prototype
- Bật rule sets cơ bản tiếng Việt/English; mẫu keyword lists cung cấp sẵn.
- Mặc định health templates require disclaimer + human review if any high-risk match.
- Không tự động xóa hoặc sửa text của user; chỉ gợi ý và cho phép block export cho publish.
- Ghi rõ disclaimer rằng app cung cấp hỗ trợ tuân thủ kỹ thuật, không đảm bảo tuân thủ pháp lý; final responsibility thuộc người xuất bản.
Kết thúc phần này bằng cấu trúc hành động: implement manifest-driven constraints, build rule scanner with savable rule sets, add compliance panel and preflight gating, and implement audit logging and reviewer workflow trong app.
Risk register và mitigation kế hoạch
Mình liệt kê các rủi ro chính cho prototype, mức độ ảnh hưởng, likelihood (cao/trung bình/thấp) và hành động mitigation cụ thể để giảm rủi ro khi phát triển và xuất templates.
- Templates không responsive (layout vỡ trên mobile)
- Ảnh hưởng: Cao — trải nghiệm người dùng tồi, mất lead.
- Likelihood: Cao.
- Mitigation:
- Quy định bắt buộc cho mọi template: include width+height attributes, aspect-ratio CSS fallback, object-fit:cover, max-width:100% cho img.
- Tạo validation pre-export: kiểm tra mọi vùng hình và text overflow; block export nếu hero image missing hoặc image width < threshold (ví dụ 800 px cho hero) và cảnh báo cho marketer.
- Implement preview automated checks: render tại các breakpoints (320, 480, 768, 1024) và chạy visual diff cơ bản; highlight vùng bị tràn.
- Thiết kế template theo components responsive chuẩn (single-column fallback) và cung cấp guidelines cho content length (max chars cho tiêu đề/subtitle).
- Claims vi phạm pháp luật cho ngành sức khỏe/làm đẹp
- Ảnh hưởng: Rất cao — rủi ro pháp lý và uy tín.
- Likelihood: Trung bình cao.
- Mitigation:
- Template manifest cho nhóm health/beauty phải include mandatory disclaimer block và require_consent flag cho before/after.
- Rule-based scanner tích hợp sẵn kiểm tra keyword/regex (configurable) và gắn severity. Block publish export nếu có high-risk matches.
- Publish flow có hai bước: Draft export (không public) và Publish export (phải qua human-in-the-loop review nếu có high-risk findings).
- Lưu audit trail cho mọi export publish (user, timestamp, snapshot) để phục vụ compliance review.
- Hiển thị inline highlight và suggested rephrases cho nội dung bị báo nguy.
- Hình ảnh thiếu bản quyền hoặc metadata không đủ
- Ảnh hưởng: Cao — rủi ro bản quyền, có thể phải gỡ page.
- Likelihood: Trung bình.
- Mitigation:
- Khi user import ảnh, yêu cầu điền nguồn/owner/consent checkbox cho ảnh before/after; lưu metadata trong project JSON.
- Cảnh báo rõ ràng khi dùng ảnh từ clipboard/link không rõ nguồn; cung cấp placeholders gợi ý và liên kết tới nguồn stock trả phí ngoài app.
- Trong preflight, nếu bất kỳ ảnh nào không có metadata consent, mark as warning/block publish cho templates health.
- Hướng dẫn người dùng cách chọn và ghi nhận license; cung cấp mẫu text for licensing.
- Kích thước package quá lớn khi export self-contained
- Ảnh hưởng: Trung bình — khó gửi, deploy chậm.
- Likelihood: Trung bình cao.
- Mitigation:
- Export modes: light (references CDN fonts/images) vs self-contained (include assets). Warn user rõ ràng về kích thước for self-contained.
- Client-side immediate image preprocessing tạo srcset (480, 768, 1200, 1920) và tạo WebP; optional background native batch optimize (sharp) trước khi export.
- Limit in-project originals bằng mặc định (auto-resize on import) và cung cấp report kích thước tổng trước zipping.
- Minify CSS/HTML, optionally remove unused CSS per-template using render-then-purge with safelist rules.
- CSS/JS conflicts giữa templates hoặc inline styles từ content
- Ảnh hưởng: Trung bình.
- Likelihood: Trung bình.
- Mitigation:
- Namespace root class .sp-template-<id> cho toàn bộ CSS của từng template.
- Sanitize pasted HTML, strip inline style attributes by default; allow advanced override only in template editor with warning.
- Build per-template CSS bundles; run scoped purge against rendered HTML.
- Image processing failures or long blocking tasks
- Ảnh hưởng: Trung bình.
- Likelihood: Trung bình.
- Mitigation:
- Use hybrid pipeline: fast client-side preview transforms, optional background native optimization. Run heavy tasks off main UI thread and show progress.
- Retry logic and graceful degrade: if native binary not available, fallback to JS resize and mark for later optimization.
Tổng kết hành động ưu tiên
- Áp ngay template manifest với required fields và media rules.
- Bật preflight validation và rule-based scanner cho health templates.
- Thiết lập image ingestion pipeline hybrid và export modes rõ ràng.
- Scope CSS bằng namespace và sanitize nội dung.
Roadmap phát triển và milestones cho prototype → production
Mục tiêu: đưa một ứng dụng PC prototype có thể tạo và xuất sale page responsive (ít nhất 8 mẫu minh họa) từ content có sẵn, rồi tiến tới bản beta có authoring template và quy trình tuân thủ, cuối cùng là sản phẩm production với marketplace và analytics. Dưới đây là lộ trình 3 pha, mốc thời gian đề xuất và deliverables cụ thể cho mỗi mốc. Mốc thời gian là khung tham khảo cho một team nhỏ full-stack; bạn điều chỉnh theo nguồn lực thực tế.
Giai đoạn 1 — MVP (8 tuần)
- Thời gian đề xuất: 6–8 tuần.
- Mục tiêu chính: có app chạy trên PC (Electron hoặc Tauri) cho phép chọn template, nhập nội dung, preview responsive và xuất HTML/CSS tĩnh cho 8 mẫu minh họa.
- Deliverables:
- Core app infrastructure: project open/save local, assets folder, user project JSON schema.
- Template library cơ bản: 8 mẫu minh họa (4 sức khỏe, 4 làm đẹp) dưới dạng template package với template.json manifest.
- Editor cơ bản: form-based field editor + inline editing đơn giản + markdown block support.
- Preview responsive: switcher desktop/tablet/mobile, live render bằng Handlebars.
- Media pipeline cơ bản: client-side image normalization + generate srcset small/medium/large + WebP conversion (JS/canvas) cho preview.
- Export static: produce index.html, styles.css, assets/ và zip export. Export mode: light (external fonts) và self-contained.
- Validation preflight: required fields check, image size warnings.
- Packaging: dev build + Windows/macOS test installers.
- Kiểm tra hoàn tất: render tất cả 8 templates với sample JSON, test export and deploy to static host manually.
Giai đoạn 2 — Beta (12 tuần)
- Thời gian đề xuất: 10–12 tuần sau MVP.
- Mục tiêu chính: mở rộng khả năng authoring template, nâng cấp xử lý media, thêm compliance workflow và QA tự động.
- Deliverables:
- Template authoring UI cho admin: edit partials, upload CSS, define manifest.requiredFields, versioning templates.
- Hybrid media pipeline: integrate native optimizer (sharp/libvips) as optional background task for higher-quality WebP/AVIF variants.
- Compliance tooling: template flags for health/beauty, mandatory disclaimer block, rule-based scanner (keyword/regex) và publish vs draft export flow with manual approval gate.
- Advanced export optimizations: per-template CSS purge (render-then-purge), minify pipeline, critical CSS extraction.
- Automated QA: visual regression snapshots for templates + responsive checks across key viewports using Playwright/Puppeteer.
- Form integrations: webhook templates, Zapier/Make guides, exportable form payload examples.
- Beta packaging and internal distribution + user feedback collection workflow.
- Kiểm tra hoàn tất: run automated visual tests; compliance scanner tuned on sample corpus; onboard small group of marketers for usability feedback.
Giai đoạn 3 — Production (16–24 tuần)
- Thời gian đề xuất: 4–6 tháng after Beta.
- Mục tiêu chính: ổn định, scale, và mở marketplace templates + multi-language + analytics.
- Deliverables:
- Marketplace & template registry: import/export zip, signatures, rating/review, paid/free flags.
- Multi-language support: i18n schema, per-template locale variants, RTL handling if cần.
- Analytics & A/B: integrate lightweight analytics snippets and export option for A/B variants tracking; dashboard summary in-app for publish stats.
- CDN/upload workflow (optional): integrations to upload assets during export to S3/Cloudinary for self-hosted optimized delivery.
- Security/compliance hardening: audit logs for publish actions, opt-in telemetry, data encryption for cloud sync.
- Installer & release pipelines: automated CI/CD to produce signed installers for Windows/macOS/Linux, update mechanism.
- Documentation & onboarding: template author guide, compliance playbook, export/deploy guide for marketers.
- Kiểm tra hoàn tất: run production-scale tests, marketplace onboarding of third-party templates, finalize legal checklist.
Timeline tổng quát tham khảo: MVP 2 months, Beta 3 months, Production 4–6 months. Mỗi mốc kèm checklist QA và release notes. Prioritize feedback loop giữa marketers và compliance team trong Beta để giảm rủi ro pháp lý trước khi lên Production.
Tài liệu cần viết kèm và checklist handover
Mục tiêu: cung cấp bộ tài liệu đầy đủ để handover dự án prototype ứng dụng PC tạo sale page. Dưới đây là danh sách tài liệu cần giao kèm và outline mẫu cho mỗi file. Mỗi outline là bản điền sẵn để bạn chuyển thành tài liệu hoàn chỉnh.
- template.json spec — mục đích: chuẩn hóa package template
- Header: templateId, version, name, category, author, license
- fields: danh sách trường với schema (path, type, required, default, validation: maxLength, pattern, aspectRatio)
- partials: tên partials và file path
- themeTokens: list variables (color, font, spacing) và giá trị mặc định
- assets: required asset list với minWidth/minHeight/kind (image/svg)
- exportRules: breakpoints, criticalCssHints, inlineCritical boolean
- compliance: flags (healthTemplate boolean, requiredDisclaimer boolean)
- example: một template.json hoàn chỉnh mẫu cho “Clinical Offer”
- Contributor guide cho template authors — mục đích: hướng dẫn tạo template đúng chuẩn
- Quickstart: cấu trúc thư mục template, naming convention
- Handlebars conventions: helpers allowed, partial usage, escaping rules
- CSS scoping: root class pattern .sp-template-<id>, use of CSS variables
- Images: recommended srcset sizes, naming, metadata fields in manifest
- Accessibility checklist per template
- Versioning and changelog format
- Example: step-by-step tạo một partial hero.hbs và cập nhật template.json
- Runbook export — mục đích: quy trình xuất/khắc phục lỗi export
- Preflight checklist: schema validation, image warnings, compliance flags, missing fields
- Export steps: render → generate srcset → inject theme → minify → package zip
- Commands: node scripts / CLI commands kèm ví dụ lệnh
- Error handling: common errors và cách fix (missing asset, purgeCSS removed classes)
- Rollback: restore last valid export, where tìm log
- Example: log snippet và mẫu đầu ra index.html structure
- User help cho marketer — mục đích: hướng dẫn sử dụng nhanh
- Creating project, choosing template, replacing images, editing text (form + inline)
- Quick tips: recommended hero image sizes, CTA best practices, disclaimer insertion
- Export options explained: light vs self-contained, webhook form setup
- Troubleshooting FAQ: image too large, CTA not visible on mobile
- Example: checklist publish-ready (meta, og image, form action)
- QA checklist — mục đích: kiểm tra trước khi giao file cho khách
- Functional: all CTAs clickable, forms post correctly, links not 404
- Responsive: list viewports to test (320, 375, 768, 1024, 1366)
- Visual: compare against reference mock, no layout overflow, images not pixelated
- Performance/accessibility: meta viewport, alt text, color contrast, lazy-load
- Export integrity: assets present, paths relative, zip content validation
- Example: mẫu báo cáo QA pass/fail cho một template
- Build + release guide cho DevOps — mục đích: build, package, release
- Dev prerequisites: Node, Rust (if Tauri), native binaries list (sharp/libvips)
- Build steps: dev run, production build commands, environment variables
- Packaging: electron-builder or tauri bundler config snippets, codesign notes
- CI pipeline: tests to run, artifact storage, auto-update setup
- Release checklist: notarization, release notes, smoke test
- Example: sample CI YAML snippet và artifact layout
Kèm mỗi doc: một bản mẫu hoàn chỉnh (filled example) để dev có thể chạy thử ngay. Các file cấu trúc phải versioned và lưu trong repo docs/ với quy ước tên rõ ràng để dễ tra cứu.
Kết luận
Mình tin rằng sau khi bạn áp dụng khung kỹ thuật và checklist này, đội phát triển sẽ có lộ trình rõ ràng để dựng một ứng dụng PC local-first giúp marketer tạo và xuất sale page tĩnh an toàn, nhất quán và dễ kiểm soát. Lưu ý thực tế quan trọng nhất: hãy giữ ranh giới rõ ràng giữa preview client-side và export server-side/native để đảm bảo preview nhanh cho marketer trong khi export vẫn tạo ra HTML/CSS/asset deterministically và tuân thủ mọi kiểm tra preflight.