Build Wechat Miniprogram From Prd Html
Build WeChat Mini Program pages from PRD HTML or static web mockups without carrying over unsupported web syntax. Prefer the existing project's patterns first, keep compatible TailwindCSS utility classes in place, then prefer tdesign-miniprogram components and icons before custom markup.
Workflow
Read the source artifact carefully.
- Extract page sections, states, data fields, interactions, and repeated blocks.
- Decide whether the request is a full page, a component slice, or a targeted edit.
Inspect the target project before writing code.
- Find similar pages or components with
rg -n "usingComponents|<t-|tdesign-miniprogram" src. - Confirm page file structure, style file type, naming, and event-binding conventions.
- Find similar pages or components with
- Verify TDesign icon names against local
node_modules/tdesign-miniprogram/miniprogram_dist/icon/icon.wxssbefore selecting icons. - Read references/project-conventions.md when working in an existing project.
- Plan the conversion in mini-program terms.
- Re-map web DOM into
view,text,image,block,scroll-view, and TDesign components. - Replace inline SVG or icon fonts with
t-iconfirst. - For check/toggle interactions (permission switch, enable/disable state), prefer
t-switchfirst, thent-checkboxort-radio-groupwhen semantics require it. Avoid handcrafted Tailwind peer-selector toggles. - Keep the original TailwindCSS utility class intent whenever the class is compatible with the project's mini-program Tailwind setup.
- Decide which data should live in
*.js, which components must be registered in*.json, and which layout rules belong in*.scssonly when utility classes are insufficient or awkward. - Read references/html-to-miniprogram.md for tag mapping and component selection.
- Re-map web DOM into
- For long popup branch content (for example
wx:elifrisk detail), extract into a dedicated component and pass a structured object from page data.
- Implement the result as mini-program files.
- Write
*.wxmlwith mini-program syntax only. - Update
*.jsonto register everytdesign-miniprogramcomponent used. - Add or update
*.jsdata, lifecycle hooks, and handler stubs needed by the page.
- Write
- When popup branch conversion introduces a new component, register it in page
usingComponentsand register TDesign dependencies in componentusingComponents. - Preserve TailwindCSS utility classes in
*.wxmlwhenever they already express the desired layout and visual style clearly. - Add or update
*.scssonly for layout, spacing, typography, and local overrides that are not cleanly expressed with existing utility classes.
- Review the result against the source PRD.
- Keep visual hierarchy and interaction intent, but simplify brittle web-only structure when needed.
- Remove raw HTML tags, DOM-only events, React/Vue syntax, and unsupported inline SVG.
- Check
wx:if,wx:for,bindtap,slot, component registration, and placeholder data completeness.
- Confirm branch trigger paths exist; if missing, add temporary/mock data to open and verify each branch during development.
Output Contract
- Produce native mini-program code, not HTML pasted into WXML.
- Prefer existing project components and composition patterns over inventing a new design language.
- Preserve compatible TailwindCSS class expressions from the source whenever possible instead of rewriting them into custom SCSS.
- Prefer
tdesign-miniprogramfor common UI building blocks such as nav, cells, cards, tabs, buttons, forms, dialogs, tags, loading, and icons. - Prefer
t-iconover inlinesvg, iconfont fragments, or raw path markup. - For check-like UI controls, prefer TDesign controls (
t-switch,t-checkbox,t-radio-group) instead of customview+ pseudo-element toggles. - Register components explicitly in the page or component
*.json. - Keep units and layout choices aligned with the project; preserve existing utility classes first and default to
rpxwhen creating new styles in*.scss. - Keep data-driven or repeated regions in
*.js+wx:forrather than hardcoding every item. - Treat popup branch content as extractable component units with explicit page->component data contracts.
Conversion Rules
- Convert
div,section,article,header,footer,main, andasideintoviewunless a better mini-program container exists. - Convert inline labels into
textwhen that improves clarity. - Convert
imgintoimageort-image. - Convert
buttonintot-buttonwhen the UI is a standard action. - Convert check/toggle UI into
t-switch,t-checkbox, ort-radio-groupfirst instead of custom peer-based switch markup. - Keep TailwindCSS utility classes on converted nodes whenever those classes are already supported by the project's mini-program Tailwind pipeline.
- Convert settings, list rows, and profile rows into
t-cell-group+t-cellwhere appropriate. - Convert repeated icon badges, metrics, or shortcuts into
t-grid+t-grid-itemwhen that matches the layout. - Convert tabs, pickers, uploaders, notices, dialogs, and form controls into their TDesign counterparts before writing custom primitives.
- Drop only Tailwind classes that are web-only, unsupported, or made irrelevant by the chosen mini-program component.
- Avoid Tailwind peer variants like
peer-checked:*andpeer-focus:*for toggle behavior; these often compile into sibling selectors such as~, which can cause WXSS compile incompatibilities. - Replace
onclick,onchange,className,style={{}},v-if,v-for,@click, and JSX fragments with mini-program syntax.
PRD HTML Interpretation
- Treat the PRD as intent, not as a literal DOM contract.
- Preserve information architecture, module ordering, and key interactions.
- Normalize overly absolute-positioned or decorative web layouts into maintainable mini-program structure when possible.
- If the PRD includes unsupported or ambiguous behavior, implement a sensible mini-program fallback and state that assumption.
References
- Read references/html-to-miniprogram.md for element mapping, unsupported-pattern cleanup, and TDesign-first selection rules.
- Read references/project-conventions.md for project-specific implementation conventions and example paths.
- Read references/page-pr-checklist.md before delivery for route wiring and nested-loop safety checks.
Practical Lessons: Popup HTML -> Mini Program Component
For PRD snippets that belong to popup branch content:
- Do not leave long branch HTML inline in page WXML. Convert once, then extract to dedicated component immediately.
- Convert icons with
t-icon(for exampleactivity,heart,time) rather than inline SVG paths. - Use a single object prop contract (for example
exerciseData,sleepData) to carry title/time/summary/advice list. - Keep repeated advice rows data-driven with
wx:for; avoid hardcoding each row in page template. - Update three layers together: page branch markup, page data object, page
usingComponentsregistration. - Include a final cleanup scan to ensure no raw web tags remain in converted branch blocks.
Practical Lessons: Popup Scroll Ownership
When converting PRD/web popup content into mini-program t-popup, enforce a single vertical scroll owner.
- Use one
scroll-viewfor long popup content; recommended wrapper:<scroll-view type="list" scroll-y style="height: 80vh">...</scroll-view>. - Avoid dual scrolling on the same axis:
- do not keep both outer popup
scroll-viewand child componentscroll-view, - do not mix
scroll-viewwith duplicated rootoverflow-y/max-heightconstraints.
- do not keep both outer popup
- If popup needs fixed header + scrolling content, split into
header+scroll bodystructure. - Keep all popup branches under the same scroll pattern to avoid inconsistent gesture behavior.
- During refactor, verify overflow and gestures on both DevTools and real device.
Practical Lessons: Card-Embedded Insight Popup
When converting PRD popup snippets that are triggered from a reusable card/component:
- Keep popup visibility state local to the component by default; do not push this state to page level unless multiple modules must coordinate popup behavior.
- Register
t-popupin the componentindex.jsonwhen popup is owned by the component. - Expose optional component events (for example
insightopen/insightclose) so the page can observe analytics or side effects without owning render state. - For PRD paragraphs that include emphasized words, model content as structured parts in JS (for example
[{ text, tone }]) and render with nested<text>+ class mapping; avoid raw HTML/rich-text injection. - Prefer popup structure as
container -> fixed header -> single scroll-view body; avoid relying on sticky header behavior inside nested scrolling because compatibility can vary across devices.
Practical Lessons: PRD List Conversion Reliability
When converting long PRD HTML list blocks (metrics, meal cards, tips) into Mini Program templates:
- Prefer data-driven rendering with
wx:forover hardcoded repeated blocks; keep values/config in*.js. - In nested loops, always set explicit inner aliases (for example
wx:for-item="nutrient"), avoid reusing outeritemto prevent shadowing and accidental binding errors. - Avoid using one dynamic class field for both container and icon text color; split into dedicated fields (for example
statusTagClassandstatusIconClass) so style intent stays clear. - Before delivery, run a quick raw-tag scan on touched WXML to ensure no
<div>/<span>/<svg>or web event attrs remain. - For detail entry cards that should navigate, complete the full path wiring in one pass: card
bindtap+ page handler +app.jsonpage registration.
Practical Lessons: Hybrid Period View Migration
When PRD requires new period reports (week/month/year) but existing day content must remain unchanged:
- Keep
dayas a legacy branch; do not force-convert it into the new PRD structure unless explicitly requested. - Extract PRD report UI into a dedicated component (for example
DietPeriodReport) and keep page template split withwx:if/wx:else. - Let page JS orchestrate two data models in parallel:
sectionsfor legacy day cards,reportDataMap+ normalized/decorated report object for period reports.
- Include all required
usingComponentstogether (legacy + new); avoid accidental removal during migration. - Keep visual parity for both branches by preserving legacy style overrides (
.day-card .remind-card ...) while scoping new styles to the new component. - Verify all tabs after migration (
day,week,month,year) to catch branch-specific regressions early.
Practical Lessons: Tailwind Fidelity and Build Reliability
When the user explicitly asks to keep PRD Tailwind classes, apply this rule set:
- Keep PRD utility classes literal in
*.wxmlfirst; avoid renaming to custom semantic classes unless required. - Do not put critical Tailwind utility class strings only in
*.jsdata/config (for exampleitem.className) because some build pipelines may not extract them reliably. - For repeated blocks, prefer literal classes in template branches over dynamic class-string assembly when style fidelity matters.
- Treat web-centric utilities as suspect in Mini Program context (
group-hover:*, hover-only effects, some blur/filter utilities, complex opacity slash variants likeshadow-*/30); provide explicit fallback style in*.scsswhen needed. - Do not rely on CSS list markers for
viewnodes; render explicit bullet text (•) in WXML for predictable output. - Add a post-conversion check: grep
dist/app.wxssfor 3-5 load-bearing PRD classes to confirm they were generated before delivery.
Practical Lessons: Center Popup List Visibility
When a converted center popup (t-popup placement="center") renders blank or appears to have "no content", apply this checklist:
- For popup-internal
scroll-view, set explicit viewport height inline first:<scroll-view type="list" scroll-y style="height: 80vh">...</scroll-view>.
- Do not rely only on class-based
max-heightfor the first implementation; in some layouts this can still produce zero/insufficient render height. - Keep one vertical scroll owner. If the child component owns scroll, remove extra popup/page wrappers that also scroll on Y.
- Keep popup option-row style ownership inside the popup component stylesheet (icon wrap color class, icon color class), instead of depending on page stylesheet injection.
- Verify end-to-end trigger chain in one pass:
- page
visiblestate update, bind:visible-changesync,- component
close/selectevents.
- page
- Avoid relying on
wxmlarray-index expressions for critical label rendering (for example{{relationOptions[relationIndex]}}); prefer a derived display field indatasuch asselectedRelation. - In component
propertiesobservers, initialize popup form state with directsetDataor guarded logic; avoid fragile observer -> method indirection as the first render path. - Keep popup shell visuals (
background,border-radius,shadow, width) in the popup component stylesheet/class, not only utility classes on the root node. - For popup body
scroll-view, use explicit height + max-height fallback together on first implementation (for exampleheight: 960rpx; max-height: 76vh;) to reduce blank-content risk across devices.
Practical Lessons: Tailwind-First + Node Semantics
When the user explicitly asks to keep PRD Tailwind classes, and especially when converting badge/chip/tag rows:
- Keep Tailwind utility classes in WXML as the first implementation path; do not prematurely rewrite equivalent styles into custom SCSS class names.
- If a node carries layout/box responsibilities (
px-*,py-*,rounded-*,border-*,w-*,h-*,flex-*, margin/padding/display), useviewas the container node. - Reserve
textfor textual semantics only; for chip/badge patterns useviewwrapper + innertext. - During review, run a quick structure pass on touched WXML:
- find
textnodes with obvious layout utility classes, - convert those wrappers to
viewwhile keeping inner text rendering unchanged.
- find
- Prefer this conversion order for stability:
- PRD utility classes preserved in WXML,
- minimal SCSS supplement only when utility classes are insufficient.
Practical Lessons: First-Pass Delivery Completeness
For new page conversion tasks, complete route + page + component wiring in one pass before reporting done:
- Create/verify full page quartet:
index.json,index.wxml,index.js,index.scss|wxss. - Register page path in
src/app.jsonbefore handoff. - Register all child components in page
usingComponentsand ensure component files (js/json/wxml/scss) are all present. - If color/style is requested from PRD, verify both:
- page-level background and card gradients,
- component-level style ownership for critical blocks.