preline-mcp
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChinesePreline MCP
Preline MCP
Intent
用途
Use this skill to integrate Preline UI components and blocks into HTML files via the Preline MCP server. The server exposes 6 tools that return integration-ready HTML, CSS, and JS.
Activate when:
- User says "preline", "add preline", "/preline", "use preline"
- User asks for a Tailwind CSS component from the Preline library
- User asks for a block (ready-made page section) or a starter page
使用本技能通过Preline MCP服务器将Preline UI组件和区块集成到HTML文件中。该服务器提供6个工具,可返回可直接用于集成的HTML、CSS和JS代码。
在以下场景激活:
- 用户提及“preline”、“add preline”、“/preline”、“use preline”
- 用户请求来自Preline库的Tailwind CSS组件
- 用户请求区块(现成的页面区段)或起始页面
Defaults
默认规则
- Never guess slugs. All section, component, and category identifiers are exact kebab-case strings. Always discover them via or
components_listfirst.blocks_categories - One at a time. Retrieve one component or block, integrate it fully, then move to the next.
- Always read the target file before inserting anything.
- Call when the component type is known - this keeps the response small. Omit section only when unsure.
components_list({ section: "<inferred-slug>" })
- 绝不猜测标识符:所有区段、组件和分类的标识符均为精确的短横线分隔字符串(kebab-case)。必须先通过或
components_list工具获取这些标识符。blocks_categories - 一次处理一个:获取一个组件或区块,完成完整集成后,再处理下一个。
- 插入前务必读取目标文件
- 当已知组件类型时,调用——这样能缩小响应范围。仅当不确定时才省略section参数。
components_list({ section: "<inferred-slug>" })
Decision: Component vs Block
组件与区块的选择决策
| User says | Use |
|---|---|
| "component" / "components" | Component workflow |
| "block" / "blocks" (or "example" / "examples") | Block workflow |
| Ambiguous | Use judgment; blocks give more complete results |
| 用户表述 | 使用流程 |
|---|---|
| "component" / "components" | 组件工作流 |
| "block" / "blocks"(或"example" / "examples") | 区块工作流 |
| 表述模糊 | 自行判断;区块会提供更完整的结果 |
Clarifying Vague Requests
模糊请求的澄清
Ask the user to pick instead of guessing in either of these cases:
- Abstract request. Too abstract to confidently map onto one category/section, let alone one block/component - e.g. "give me something for a pricing page", "I need a nice form", "show me a dashboard example". Start at step 1 below.
- Tied candidates. The request is concrete enough to reach a single category/section, but /
blocks_in_categorystill leaves 2+ candidates whose titles + descriptions satisfy every criterion the request named about equally well (same layout/feature/style class), with nothing in the request to break the tie. Skip straight to step 3 below with just the tied candidates.components_list({ section })
If exactly one candidate matches everything the request names ("a basic accordion", "the SaaS hero with tabs"), skip straight to the normal workflow - don't interrogate the user for things you can already resolve, and don't ask just to be safe when one option is clearly the best fit.
All clarifying questions and lists are in English by default - switch to the user's language only once they write to you in it.
Blocks:
- Ask which category fits. Call and present the relevant
blocks_categories()paths with their titles and descriptions - the catalog carries a one-line description for every category, so present it directly rather than inventing your own summary.mainSection / subSection / category - Try to resolve in one round. If the user's reply both names a category and describes the item distinctively enough to identify a single match (a specific layout, feature, or style), call to confirm the exact ID and go straight to
blocks_in_category- skip step 3 entirely.single_block - Otherwise, ask which block fits best. Call , list the block titles + descriptions - or just the tied candidates, for the case above - and ask the user to pick the one closest to their needs.
blocks_in_category({ mainSection, subSection, category }) - Fetch and integrate the chosen block with .
single_block
Components - same shape, sections instead of categories:
- Ask which section fits (for the full list, or
components_list()once you can infer one).components_list({ section }) - If the reply names a section and describes the component distinctively enough → resolve directly via (lean on
single_componentmetadata - see Smart Component Selection - to land on the right default/variant).relative - Otherwise list the components in that section (titles + descriptions, with groupings where present - or just the tied candidates, for the case above) and ask which fits best.
relative.category - Fetch and integrate with .
single_component
Keep each round to one focused question with a short, scannable list - that beats an open "what do you want?" and beats guessing a slug just to avoid asking.
在以下两种情况中,请让用户选择而非自行猜测:
- 抽象请求:过于抽象,无法确定对应的分类/区段,更无法确定具体的区块/组件——例如“给我一个定价页面的内容”、“我需要一个好看的表单”、“展示一个仪表盘示例”。从下方步骤1开始处理。
- 候选结果不分伯仲:请求足够具体,能定位到单个分类/区段,但/
blocks_in_category返回的2个及以上候选结果,其标题和描述均同等符合请求中的所有标准(布局/功能/样式类别相同),且请求中没有信息能区分这些候选结果。直接跳至下方步骤3,仅列出这些不分伯仲的候选结果。components_list({ section })
如果恰好有一个候选结果完全匹配请求中的所有内容(例如“基础折叠面板”、“带标签页的SaaS首页横幅”),直接进入常规工作流——无需向用户询问已能确定的内容,且当有明确最优选项时,不要为了保险而询问。
所有澄清问题和列表默认使用英文——仅当用户使用其他语言回复时,才切换为用户的语言。
区块流程:
- 询问合适的分类:调用工具,展示相关的
blocks_categories()路径及其标题和描述——目录中每个分类都有一行描述,请直接展示该描述,不要自行总结。mainSection / subSection / category - 尝试一轮解决:如果用户的回复既指定了分类,又能足够独特地描述所需内容(特定布局、功能或样式),调用工具确认精确ID,直接进入
blocks_in_category步骤——完全跳过步骤3。single_block - 否则,询问合适的区块:调用工具,列出区块标题和描述——或仅列出上述不分伯仲的候选结果——并请用户选择最符合需求的选项。
blocks_in_category({ mainSection, subSection, category }) - 获取并集成:通过工具获取所选区块并完成集成。
single_block
组件流程——与区块流程类似,仅将分类替换为区段:
- 询问合适的区段(调用获取完整列表,或在能推断出区段时调用
components_list())。components_list({ section }) - 如果回复指定了区段,且能足够独特地描述组件→直接通过工具获取(借助
single_component元数据——参见智能组件选择——选择正确的默认/变体)。relative - 否则列出该区段下的组件(标题和描述,如有分组则按分组展示——或仅列出上述不分伯仲的候选结果),并请用户选择最符合需求的选项。
relative.category - 通过工具获取并集成。
single_component
每一轮仅提出一个聚焦的问题,并附带简短易读的列表——这比开放式的“你想要什么?”更好,也比为了避免询问而猜测标识符更好。
Composite & Layout Requests
复合与布局请求
When a request describes more than a single component - several pieces, a region, a full page, or an app shell - don't fetch ad-hoc. Plan the whole result first, then fetch and integrate one node at a time. The same steps apply to any shape: a dashboard, a settings page, a product page, a multi-step form, "a card/section/layout with X, Y and Z", etc.
- Lock cross-cutting constraints first. Anything that applies to the whole result - class system (theme tokens vs utilities → /
isUtilityBased), shared surfaces/colors, spacing/density, repeated element states - decide once, up front. Keep it identical across every later fetch and edit.theme - Decompose into a tree: containers → regions → leaf components. Write it down; each leaf is one fetch.
- Discover every node - route, then confirm. Use references/catalog-map.md to route: an abstract intent (a whole page/region/shell) → the right branch (reuse a ready-made block as the skeleton when one fits); each named element → the right
blocks_categories. The map only tells you where to look - always confirm the exact slug against the tool output before inserting.components_list({ section }) - Assemble outermost-first, one at a time. The skeleton/outer container sets the shared surfaces and the script/init anchors; then fill inward region by region, integrating each fully (Integration Rules) before the next. Keep the returned classes, change text only - except the specific surfaces/colors/states the user asked to change. Apply every structural adaptation to the markup before writing it (see Adapt before you write in Integration Rules).
- Verify the finished result against the request, element by element.
See references/composite-layouts.md for the expanded method and worked illustrations.
当请求描述不止一个组件时——多个元素、一个区域、完整页面或应用框架——不要临时获取内容。先规划完整结果,再逐个获取并集成每个节点。以下步骤适用于任何场景:仪表盘、设置页面、产品页面、多步骤表单、“包含X、Y、Z的卡片/区段/布局”等。
- 先确定全局约束:适用于整个结果的所有内容——类系统(主题令牌vs工具类→/
isUtilityBased)、共享界面/颜色、间距/密度、重复元素状态——提前一次性确定。在后续所有获取和编辑操作中保持一致。theme - 分解为树形结构:容器→区域→叶子组件。记录下来;每个叶子节点对应一次获取操作。
- 查找每个节点——先定位,再确认:使用references/catalog-map.md进行定位:抽象需求(完整页面/区域/框架)→对应的分支(当有合适的现成区块时,复用该区块作为骨架);每个指定元素→对应的
blocks_categories。该地图仅告诉你去哪里找——插入前务必通过工具输出确认精确的标识符。components_list({ section }) - 从最外层开始组装,一次一个:骨架/外层容器设置共享界面和脚本/初始化锚点;然后逐个填充内部区域,完成每个节点的完整集成(参见集成规则)后再处理下一个。保留返回的类,仅修改文本——除非用户要求修改特定的界面/颜色/状态。在写入前,先对标记语言进行所有结构调整(参见集成规则中的“写入前调整”)。
- 验证:对照请求,逐个元素检查最终结果。
如需扩展方法和示例说明,请参阅references/composite-layouts.md。
Workflow: Components
组件工作流
1. components_list({ section: "<slug>" }) → get valid component IDs
2. single_component({ section, component }) → get HTML/CSS/JS
3. Read target file
4. Integrate HTML, CSS, scripts, init (see Integration Rules)
5. Repeat from step 1 only after integration is complete1. components_list({ section: "<slug>" }) → 获取有效的组件ID
2. single_component({ section, component }) → 获取HTML/CSS/JS代码
3. 读取目标文件
4. 集成HTML、CSS、脚本和初始化代码(参见集成规则)
5. 仅在集成完成后,才从步骤1重复操作Workflow: Blocks
区块工作流
1. blocks_categories() → get hierarchy
2. blocks_in_category({ mainSection, subSection, category }) → get block IDs
3. single_block({ mainSection, subSection, category, block }) → get HTML/CSS/JS
4. Read target file
5. Integrate HTML, CSS, scripts, init (see Integration Rules)
6. Repeat from step 1 only after integration is complete1. blocks_categories() → 获取分类层级
2. blocks_in_category({ mainSection, subSection, category }) → 获取区块ID
3. single_block({ mainSection, subSection, category, block }) → 获取HTML/CSS/JS代码
4. 读取目标文件
5. 集成HTML、CSS、脚本和初始化代码(参见集成规则)
6. 仅在集成完成后,才从步骤1重复操作Integration Rules
集成规则
HTML - insert where the user needs it.
CSS ( section):
<!-- CSS -->- MUST go inside , immediately before
<head></head> - NEVER place in or near
<body></body>
External scripts ( section):
<!-- Scripts -->- The label is a response section marker - NOT a location in the target file
<!-- Scripts --> - Placement algorithm: open target file, scan upward from , skipping blank lines, comments, and non-structural tags (
</body>,</script>, etc.)</style> - The first structural closing tag you reach (,
</main>,</section>,</div>,</footer>) is the anchor</article> - Insert tags after that anchor, ordered around the existing Preline core script - the loaded
<script src>whose<script src>containssrc(e.g.preline; exact path varies by install):…/preline/dist/index.js- scripts whose does not contain
src(third-party libs: lodash, apexcharts, …) → before the Preline core scriptpreline - scripts whose does contain
src(Preline helpers, e.g.preline) → after the Preline core scripths-*-helpers.js - if no Preline core script exists yet, keep order: scripts without , then scripts with
prelinepreline - inline init always comes last, immediately before
<script></body>
- scripts whose
Init ( section):
<!-- Init -->- Place immediately before
</body> - Wrap in unless the block already contains
window.addEventListener('load', () => { ... })tags<script>
Large responses (artifacts): when a response is written to a temp scratch file, read it once with the Read tool (use offset/limit for big files), copy the needed blocks into the target, then delete the scratch file. Don't pull the whole artifact into context if you only need to place it.
Adapt before you write. When the request differs from the fetched markup - regions the user didn't ask for (breadcrumbs, demo menus, placeholder logos), different blocks or labels - produce the final markup in memory first, then write it into the target in ONE edit per region. Never insert fetched markup wholesale and refactor it with a chain of follow-up edits: every such edit re-transfers large markup, bloats context, and desyncs file state.
Same token = same color. Theme tokens (, , , …) are consistent across a theme - to give two surfaces the same color, give them the same token class. Never resolve tokens to raw colors by reading the project's CSS.
bg-navbarbg-sidebarbg-layerTrust the returned markup - do not re-verify it. The classes, structure, and attributes the MCP returns are valid Preline by construction. This is the single biggest time-sink to avoid. Do NOT:
data-hs-*- grep, parse, or scan the user's compiled CSS (e.g. ) to "confirm" a class exists or to resolve what color a design token produces - Preline classes resolve at the consumer's build step, so absence from any one stylesheet means nothing;
main.css - write HTML/DOM/AST validators (Python , tag-balance checkers, etc.) - SVG and void elements trip naive parsers and produce false errors;
HTMLParser - re-read a placed artifact or re-open the edited file just to "double-check" the generated code.
Place the markup, change text only, move on. Verify against the request (is every element the user named present?), never by auditing the generated code or the project's CSS.
HTML——插入到用户指定的位置。
CSS(区段):
<!-- CSS -->- 必须放在标签内,紧邻
<head>之前</head> - 绝不能放在标签内或
<body>附近</body>
外部脚本(区段):
<!-- Scripts -->- 标签是响应区段标记——而非目标文件中的位置
<!-- Scripts --> - 放置算法:打开目标文件,从向上扫描,跳过空行、注释和非结构性标签(
</body>、</script>等)</style> - 找到的第一个结构性闭合标签(、
</main>、</section>、</div>、</footer>)即为锚点</article> - 在该锚点之后插入标签,围绕已有的Preline核心脚本排序——即src包含
<script src>的已加载preline(例如<script src>;具体路径因安装方式而异):…/preline/dist/index.js- src不包含的脚本(第三方库:lodash、apexcharts等)→ 放在Preline核心脚本之前
preline - src包含的脚本(Preline辅助脚本,例如
preline)→ 放在Preline核心脚本之后hs-*-helpers.js - 如果尚未存在Preline核心脚本,保持顺序:先放不含的脚本,再放含
preline的脚本preline - 内联初始化始终放在最后,紧邻
<script>之前</body>
- src不包含
初始化代码(区段):
<!-- Init -->- 放在紧邻之前的位置
</body> - 除非区块已包含标签,否则需包裹在
<script>中window.addEventListener('load', () => { ... })
大体积响应(工件):当响应被写入临时文件时,使用读取工具读取一次(大文件可使用offset/limit参数),将所需部分复制到目标文件,然后删除临时文件。如果仅需放置内容,不要将整个工件拉入上下文。
写入前调整:当请求与获取的标记语言不符时——用户未要求的区域(面包屑、演示菜单、占位符logo)、不同的区块或标签——先在内存中生成最终的标记语言,然后一次性写入目标文件的对应区域。绝不要直接插入获取的标记语言,再通过一系列后续编辑进行重构:每次此类编辑都会传输大量标记语言,膨胀上下文,并导致文件状态不同步。
同一令牌=同一颜色:主题令牌(、、等)在主题中保持一致——要让两个界面颜色相同,给它们添加相同的令牌类。绝不要通过读取项目的CSS将令牌解析为原始颜色。
bg-navbarbg-sidebarbg-layer信任返回的标记语言——无需重新验证:MCP返回的类、结构和属性天生符合Preline规范。这是最需要避免的耗时操作。请勿:
data-hs-*- 搜索、解析或扫描用户的编译CSS(例如)来“确认”某个类是否存在,或解析设计令牌对应的颜色——Preline类在消费者构建步骤中解析,因此在某一样式表中不存在并不代表无效;
main.css - 编写HTML/DOM/AST验证器(Python 、标签平衡检查器等)——SVG和空元素会导致简单解析器出错,产生误报;
HTMLParser - 重新读取已放置的工件或重新打开编辑后的文件来“再次检查”生成的代码。
放置标记语言,仅修改文本,继续下一步。对照请求验证(用户指定的每个元素是否都存在?),绝不要通过审核生成的代码或项目的CSS来验证。
Smart Component Selection
智能组件选择
components_listrelative- - recommended default for the section; prefer when the request is vague
isSectionDefault: true- Exception: if the description says "multiple variants" and the user wants one, pick a single-variant component instead
- - logical group (e.g.
category,"color-variants")"states" - - recommended default for its category; prefer when the request implies a style group
isCategoryDefault: true
components_listrelative- ——该区段的推荐默认组件;当请求模糊时优先选择
isSectionDefault: true- 例外:如果描述中提到“多个变体”且用户只需要一个,选择单变体组件
- ——逻辑分组(例如
category、"color-variants")"states" - ——该分组的推荐默认组件;当请求暗示样式分组时优先选择
isCategoryDefault: true
Available Themes
可用主题
defaultharvestretromoonoceanbubblegumcashmereautumnolivePass via on or .
isUtilityBased: true, theme: "<name>"single_componentsingle_blockdefaultharvestretromoonoceanbubblegumcashmereautumnolive在或工具中通过参数传递。
single_componentsingle_blockisUtilityBased: true, theme: "<name>"Key References
关键参考
- references/catalog-map.md - routing map: block intent ontology (whole pages/shells) + all component sections grouped by purpose, JS-plugin marked. Open this to pick the right / blocks branch before any discovery call.
section - references/composite-layouts.md - full method for multi-component / page / shell requests, with worked illustrations
- references/mcp-tools-reference.md - full parameter specs, placement algorithm detail, all 6 tools
- references/catalog-map.md——定位地图:区块需求本体(完整页面/框架)+ 按用途分组的所有组件区段,标记了JS插件。在调用任何发现工具前,打开此文件选择正确的/ 区块分支。
section - references/composite-layouts.md——多组件/页面/框架请求的完整方法,附示例说明
- references/mcp-tools-reference.md——完整参数规范、放置算法细节、所有6个工具的说明",