| name | makerworld-description |
| description | Extract MakerWorld model descriptions into git-tracked DESCRIPTION.md files, update them after model changes, or convert them back to pasteable HTML for MakerWorld's CKEditor. USE FOR: extracting descriptions from MakerWorld model pages, creating new DESCRIPTION.md files, updating existing descriptions after releases, converting markdown descriptions to HTML for MakerWorld publishing. DO NOT USE FOR: uploading files to MakerWorld, managing print profiles, or OpenSCAD model creation (use @makerworld-model agent instead).
|
š MakerWorld Description Skill
š What
Manages MakerWorld model descriptions as git-tracked DESCRIPTION.md files. Supports three flows:
- Extract (MakerWorld ā Git): Scrape a MakerWorld model page and produce a clean
DESCRIPTION.md + images
- Update (Git ā» Git): Update an existing
DESCRIPTION.md after model changes ā new changelog entries, feature bullets, images
- Publish (Git ā MakerWorld): Convert
DESCRIPTION.md to HTML for pasting into MakerWorld's CKEditor
š§ Extract Flow
Given a MakerWorld model URL, extract the description into a DESCRIPTION.md file.
Steps
-
Ask the user which model this is for and where to save it:
- Target repo (
homeracker or homeracker-exclusive)
- Model name (e.g.
core, foot, frontpanel)
- Output path defaults to
models/<name>/makerworld/DESCRIPTION.md
-
Fetch the page using fetch_webpage with query "model description details" and the MakerWorld URL.
-
Parse the Description section. The description content is between the ### Description heading and the ### Comment & Rating section. Extract only this content. Ignore:
- Navigation elements, cookie banners, footer
- Print Profile section, Bill of Materials
- Comment & Rating section and all comments
- Remixes, Related Models sections
- "We use cookies" banner
-
Clean the markdown:
- Convert extracted content to well-formatted markdown
- Preserve: headings (##, ###), bold/italic, bullet lists, numbered lists, links, images, linked images (
[](url)), horizontal rules
- Strip:
[Image: Image] placeholders, duplicate blank lines, trailing whitespace
- Keep image URLs as-is initially (they'll be downloaded next)
- Use
<img> tags instead of markdown image syntax for all images. This allows preserving the width attribute. Use width="800" for images whose native width is ā„ 800px; for smaller images use their native width. Exceptions: HomeRacker logo (width="300"), Ko-fi QR code (width="328"). Do NOT set height ā omitting it lets the browser scale proportionally. Example:
<img src="https://raw.githubusercontent.com/.../logo.webp" alt="Logo" width="800">
For linked images, wrap the <img> in an <a> tag:
<a href="https://target-url"><img src="https://raw.githubusercontent.com/.../image.webp" alt="Alt" width="400"></a>
- Alignment is lost during extraction:
fetch_webpage strips style attributes, so centered text/headings from MakerWorld come through as plain markdown. This is a known limitation. After extraction, add a note at the bottom of the DESCRIPTION.md:
<!-- TODO: Review alignment ā fetch_webpage strips style attributes. Compare with MakerWorld page and wrap centered elements in HTML blocks. -->
When fixing alignment, use:
<h2 style="text-align: center">Title</h2> for centered headings
<p style="text-align: center">...</p> for centered paragraphs, images, or links
- This renders correctly on GitHub (HTML passthrough) and in
md-to-mw.py
- Detect orphan linked images:
fetch_webpage drops <img> elements inside <a> tags, producing empty links like [](https://...). Collect all such [](url) patterns ā these are linked images whose src was lost. See step 5a for resolution
- Be aware of invisible drops:
fetch_webpage silently drops <iframe> embeds (YouTube videos, etc.) with no trace at all ā just blank whitespace. See step 5b for resolution
-
Download images:
- Identify all image URLs in the description (from
makerworld.bblmw.com CDN or other sources)
- Skip external reference images (e.g.
encrypted-tbn0.gstatic.com meme images) ā keep those as URLs
- Download MakerWorld CDN images to the assets repo:
assets/<target-repo>/models/<name>/makerworld/images/
- Use descriptive filenames based on context (e.g.
diagonal_supports.png, showcase_rack.jpg)
- After downloading, get pixel dimensions with
python cmd/export/image_dimensions.py <images-dir> (for reference only ā do not use native dimensions for width)
- Standard image width: Use
width="800" for all description images whose native width is ā„ 800px. For smaller images, use their native width. Exceptions: HomeRacker logo (width="300"), Ko-fi QR code (width="328"). This ensures a uniform look across all model descriptions.
- Check for common images: Some images are shared across all models (e.g.
collection_banner.webp, kofi_qr_code.webp). These live in assets/common/makerworld/images/. If a downloaded image already exists there (same content), delete the per-model copy and reference the common one: https://raw.githubusercontent.com/kellerlabs/assets/main/common/makerworld/images/filename.webp
- Reference model-specific images using absolute URLs in
<img> tags, applying the standard width rule above: use width="800" when the native width is ā„ 800px; otherwise use the native width. Example: <img src="https://raw.githubusercontent.com/kellerlabs/assets/main/<target-repo>/models/<name>/makerworld/images/filename.png" alt="Description" width="800">
5a. Resolve orphan linked images (from step 4):
- For each
[](url) pattern found, present the user with a numbered list showing the link target URL
- Ask the user to open the MakerWorld page in a browser and identify what image is displayed for each link (e.g. a logo, a model thumbnail, a collection banner)
- The user should provide the image URL (right-click ā "Copy image address") or a description
- Once URLs are obtained: download to
assets/<target-repo>/models/<name>/makerworld/images/, replace the empty link with a proper linked image using absolute URL: [](url)
- If the user cannot provide the URL, insert a TODO comment in the markdown:
<!-- TODO: linked image missing for url -->
5b. Resolve missing embeds (from step 4):
-
Add YAML frontmatter to the top of DESCRIPTION.md:
---
makerworld_url: https://makerworld.com/en/models/<id>-<slug>
extracted: YYYY-MM-DD
---
-
Save the file to the target path.
-
Verify by reading back the file and checking:
- Frontmatter is valid YAML
- All images have been downloaded
- No
[Image: Image] placeholders remain
- No orphan
[](url) empty links remain (all resolved or marked with TODO)
- Embedded videos are accounted for (user confirmed none missing, or added)
- Markdown renders with proper heading hierarchy
š¤ Publish Flow
Convert a DESCRIPTION.md file to HTML for pasting into MakerWorld.
Steps
- Direct the user to run the conversion script:
python cmd/export/md-to-mw.py models/<name>/makerworld/DESCRIPTION.md
- This generates
DESCRIPTION.html in the same directory (gitignored).
- Instruct the user to open the HTML file in a browser, select all (
Ctrl+A), copy (Ctrl+C), then paste into MakerWorld's description editor.
ļæ½ Update Flow
Update an existing DESCRIPTION.md after model changes (new release, new features, removed parts, etc.).
Steps
-
Locate the description: Read the model's DESCRIPTION.md and its YAML frontmatter (extracted or created date, makerworld_url).
-
Detect the source repo: Infer the repo from the file path (homeracker or homeracker-exclusive). Present the suggestion and ask for confirmation before proceeding.
-
Read the changelog: Read CHANGELOG.md in the source repo. Identify releases since the frontmatter date (extracted or created) or, if no date is usable, since the last changelog entry already mentioned in the description.
-
Filter model-relevant changes: From the new releases, extract only changes that affect this model's user-facing description:
- ā
New features, new parts, breaking changes, removed parts
- ā CI/infra, docs-only, refactors, dependency bumps
Present a summary of relevant changes and ask the user to confirm or adjust before editing.
-
Update the description:
- Changelog section: Add new entries at the top of the
š Changelog list. Follow the existing emoji + version + dash + description pattern. Drop entries that are no longer the most recent 3ā4 (keep the list concise).
- Feature sections: Add, update, or remove bullets in "What's in the Box" or equivalent sections to reflect added/removed parts or features.
- Flag rewrites: If a feature was removed or significantly changed, flag the affected section with a
<!-- TODO: verify ā feature X was removed/changed in vN.N.N --> comment and ask the user for guidance.
-
Check for new images: Scan assets/<repo>/models/<name>/makerworld/images/ for images added since the last update. If new images exist, suggest where to insert them. If none exist but the new features would benefit from visuals, ask the user whether to add any.
-
Update frontmatter: Add or update the updated field with today's date:
---
makerworld_url: https://makerworld.com/en/models/<id>-<slug>
extracted: 2026-04-13
updated: 2026-04-19
---
-
Verify: Read back the file and check:
- Frontmatter dates are consistent (updated ā„ extracted/created)
- Changelog entries are in reverse-chronological order
- No stale feature bullets remain for removed parts
- Image references still resolve
-
Publish reminder: After committing, remind the user to re-run md-to-mw.py and re-paste into MakerWorld if the model is already published (check makerworld_url ā TBD).
ļæ½š File Convention
models/<name>/makerworld/
āāā <name>.scad # MakerWorld parametric source
āāā DESCRIPTION.md # Model description (source of truth)
āāā DESCRIPTION.html # Generated HTML (gitignored)
āāā renders/ # Auto-generated render previews
ā āāā <name>_mw_assembly_view.png
ā āāā <name>_mw_plate_1.png
Images are stored in the assets repo (kellerlabs/assets):
assets/<repo>/models/<name>/makerworld/images/
āāā showcase.jpg
āāā diagonal_supports.png
Common images shared across all models are stored in the assets repo:
assets/common/makerworld/images/
āāā homeracker_logo_banner.webp # HomeRacker logo (linked to homeracker.org)
āāā collection_banner.webp # Official HomeRacker Collection banner
āāā kofi_qr_code.webp # Ko-fi donation QR code
Reference via: https://raw.githubusercontent.com/kellerlabs/assets/main/common/makerworld/images/<file>
š Common Description Elements
All HomeRacker MakerWorld descriptions share recurring elements. When extracting, verify these are present:
- Centered header block ā everything from the top of the description until the first video embed or model-specific content must be centered using HTML style blocks. The logo is always
width="300" and linked to homeracker.org. Pattern:
<p style="text-align: center">Intro text</p>
<h2 style="text-align: center">Model Title</h2>
<p style="text-align: center"><a href="https://homeracker.org/"><img src=".../common/makerworld/images/homeracker_logo_banner.webp" alt="HomeRacker Logo" width="300"></a></p>
<p style="text-align: center">Subtitle / links</p>
- Collection banner ā linked image to the Official HomeRacker Collection. Uses
common/makerworld/images/collection_banner.webp
- Ko-fi QR code ā in the ā Support section. Uses
common/makerworld/images/kofi_qr_code.webp
- "š” What is HomeRacker?" section (non-core models only) ā includes the HomeRacker Core video embed (
g8k6X_axYug) immediately after the heading, followed by links to homeracker.org and the collection
These elements are often dropped by fetch_webpage (logo as orphan linked image, video as invisible iframe). Always check for them during extraction.
ā ļø Important Notes
- Cross-repo skill: Requires both the source repo (
homeracker or homeracker-exclusive) and the kellerlabs/assets repo. Maintainers push images directly to assets/main. Outside collaborators must open a PR on the assets repo for image changes.
DESCRIPTION.md is the source of truth. Always edit it in git, never in MakerWorld directly.
- After editing
DESCRIPTION.md, re-run md-to-mw.py and re-paste into MakerWorld.
- The conversion script embeds local images as base64 data URIs so the HTML is fully self-contained ā no broken links, no browser permissions needed. External image URLs (http/https) are passed through unchanged.
- Since images are now hosted in the
kellerlabs/assets repo with absolute URLs, md-to-mw.py passes them through directly ā no base64 encoding needed for assets-hosted images.
- Alignment: Use inline HTML blocks (
<h2 style="text-align: center">, <p style="text-align: center">) to preserve centered headings, images, and text from MakerWorld. These render correctly on GitHub and pass through to md-to-mw.py HTML output.
- Image sizing: Use
width="800" as the standard for all description images whose native width is ā„ 800px; for smaller images use their native width (omit height so images scale proportionally). Exceptions: HomeRacker logo (width="300"), Ko-fi QR code (width="328").
- MakerWorld CDN images (from
makerworld.bblmw.com) should be downloaded to the assets repo during extraction. External reference images (memes, badges, etc.) can stay as external URLs.
š Known Limitations
fetch_webpage drops linked images
fetch_webpage converts HTML to markdown but loses <img> elements nested inside <a> tags. This produces empty links like [](https://some-url) where a linked image (<a href="..."><img src="..."></a>) existed in the original HTML.
Common patterns affected:
- Logo/banner images linking to external sites (e.g. HomeRacker logo ā homeracker.org)
- Model thumbnail images linking to other MakerWorld models
- Collection banner images linking to MakerWorld collections
Workaround: Step 5a in the Extract Flow asks the user to manually supply the missing image URLs by inspecting the page in a browser.
fetch_webpage silently drops embedded iframes
fetch_webpage completely discards <iframe> elements (YouTube embeds, etc.) with no trace ā no placeholder, no URL, just blank whitespace. Unlike linked images which leave a detectable [](url) pattern, embedded videos are entirely invisible in the output.
Common patterns affected:
- YouTube video embeds in description sections
- Any other
<iframe>-based content
Workaround: Step 5b in the Extract Flow explicitly asks the user whether embedded videos exist on the page. Videos are stored as linked YouTube thumbnails in DESCRIPTION.md. During publish, md-to-mw.py automatically converts these to CKEditor 5 <figure class="media"> embeds with data-oembed-url, which MakerWorld's editor recognises as native video embeds.