diff --git a/public/guides/split-step-assembly-demo.png b/public/guides/split-step-assembly-demo.png new file mode 100644 index 0000000..abdd595 Binary files /dev/null and b/public/guides/split-step-assembly-demo.png differ diff --git a/public/llms.txt b/public/llms.txt index e324d16..14ef8f6 100644 --- a/public/llms.txt +++ b/public/llms.txt @@ -20,5 +20,8 @@ CAD Viewer is an open-source, in-browser CAD file viewer built on the OpenCascad ## Pricing Free to use, no subscription required. +## Guides +- How to Split a STEP Assembly Into Separate Part Files (Free, Online): https://cadviewer.xyz/guides/split-step-assembly + ## Live app https://cadviewer.xyz/ diff --git a/public/sitemap.xml b/public/sitemap.xml index 445da59..3ec7029 100644 --- a/public/sitemap.xml +++ b/public/sitemap.xml @@ -12,4 +12,10 @@ monthly 0.8 + + https://cadviewer.xyz/guides/split-step-assembly + 2026-07-26 + monthly + 0.9 + diff --git a/src/main.tsx b/src/main.tsx index b65c34d..9c5d7f1 100644 --- a/src/main.tsx +++ b/src/main.tsx @@ -2,6 +2,7 @@ import { ClientOnly, Head, ViteReactSSG } from "vite-react-ssg"; import type { RouteRecord } from "vite-react-ssg"; import App from "./ui/App"; import Landing from "./pages/Landing"; +import SplitStepAssembly from "./pages/guides/SplitStepAssembly"; function NotFound() { return ( @@ -28,6 +29,7 @@ function NotFound() { export const routes: RouteRecord[] = [ { path: "/", element: }, + { path: "/guides/split-step-assembly", Component: SplitStepAssembly }, { path: "/viewer", element: ( diff --git a/src/pages/Landing.module.css b/src/pages/Landing.module.css index 92c1dba..270a933 100644 --- a/src/pages/Landing.module.css +++ b/src/pages/Landing.module.css @@ -86,6 +86,17 @@ text-decoration: none; } +.guideLink { + margin-top: 0.5rem; + color: #93c5fd; + font-size: 0.85rem; + text-decoration: none; +} + +.guideLink:hover { + color: #3b82f6; +} + .supported { margin: 0.3rem 0 0; color: #4b5563; diff --git a/src/pages/Landing.tsx b/src/pages/Landing.tsx index a9a658b..9eff1b1 100644 --- a/src/pages/Landing.tsx +++ b/src/pages/Landing.tsx @@ -171,6 +171,10 @@ export default function Landing() { or drag a file anywhere on the page + + Need to split an assembly into parts? Read the guide → + +

Supported: STEP · IGES · STL · OBJ · 3MF · BREP · GLB · DXF

diff --git a/src/pages/guides/SplitStepAssembly.module.css b/src/pages/guides/SplitStepAssembly.module.css new file mode 100644 index 0000000..3695378 --- /dev/null +++ b/src/pages/guides/SplitStepAssembly.module.css @@ -0,0 +1,290 @@ +:global(body.guide-page) { + overflow-y: auto; + height: auto; + min-height: 100vh; +} + +:global(body.guide-page #root) { + height: auto; + min-height: 100vh; +} + +.page { + min-height: 100vh; + background: #fafafa; + color: #1a1a1a; + display: flex; + justify-content: center; + padding: 4rem 1.5rem 6rem; +} + +.article { + width: min(720px, 100%); + display: flex; + flex-direction: column; + gap: clamp(3rem, 5vw, 4rem); +} + +.section { + display: flex; + flex-direction: column; + gap: 1.25rem; +} + +.breadcrumb { + display: inline-flex; + align-self: flex-start; + color: #4b5563; + font-size: 0.9rem; + text-decoration: none; +} + +.breadcrumb:hover { + color: #3b82f6; +} + +.eyebrow { + margin: 0; + color: #6b7280; + font-family: + "SFMono-Regular", Menlo, Monaco, Consolas, "Liberation Mono", + "Courier New", monospace; + font-size: 0.75rem; + letter-spacing: 0.12em; + text-transform: uppercase; +} + +.headline { + margin: 0.5rem 0 0; + color: #1a1a1a; + font-size: 2.25rem; + line-height: 1.2; + font-weight: 700; +} + +.intro { + margin: 0; + color: #4b5563; + font-size: 1.1rem; + line-height: 1.7; +} + +.lede { + margin: 0; + color: #1f2937; + font-size: 1.1rem; + line-height: 1.7; +} + +.sectionHeading { + margin: 0; + color: #1a1a1a; + font-size: 1.5rem; + font-weight: 700; +} + +.paragraph { + margin: 0; + color: #4b5563; + font-size: 1.05rem; + line-height: 1.7; +} + +.list { + margin: 0; + padding-left: 1.25rem; + color: #4b5563; + font-size: 1.05rem; + line-height: 1.7; + display: flex; + flex-direction: column; + gap: 0.65rem; +} + +.externalLink { + color: #2563eb; + text-decoration: underline; + text-underline-offset: 2px; +} + +.externalLink:hover { + color: #1d4ed8; +} + +/* "Why you'd need to do this" cards */ +.cardList { + margin: 0; + padding: 0; + list-style: none; + display: flex; + flex-direction: column; + gap: 0.85rem; +} + +.reasonCard { + background: #f3f4f6; + border: 1px solid #e5e7eb; + border-radius: 12px; + padding: 1.1rem 1.4rem; + color: #374151; + font-size: 1.02rem; + line-height: 1.6; +} + +/* Numbered step cards */ +.stepList { + margin: 0; + padding: 0; + list-style: none; + display: flex; + flex-direction: column; + gap: 0.85rem; +} + +.stepCard { + display: flex; + align-items: flex-start; + gap: 1.1rem; + background: #ffffff; + border: 1px solid #e5e7eb; + border-radius: 12px; + padding: 1.25rem 1.5rem; +} + +.stepNumber { + flex: none; + display: inline-flex; + align-items: center; + justify-content: center; + width: 2.5rem; + height: 2.5rem; + border-radius: 999px; + background: #eff6ff; + color: #3b82f6; + font-size: 1.15rem; + font-weight: 700; +} + +.stepBody { + display: flex; + flex-direction: column; + gap: 0.3rem; +} + +.stepTitle { + margin: 0; + color: #1a1a1a; + font-size: 1.05rem; + font-weight: 700; +} + +.stepDescription { + margin: 0; + color: #4b5563; + font-size: 1rem; + line-height: 1.6; +} + +.stepImageWrap { + margin: 0.5rem 0; +} + +/* FAQ accordion */ +.faqGrid { + display: flex; + flex-direction: column; + gap: 0.75rem; +} + +.faqItem { + background: #ffffff; + border: 1px solid #e5e7eb; + border-radius: 12px; + padding: 0.35rem 1.5rem; +} + +.faqItem[open] { + padding-bottom: 1.25rem; +} + +.faqQuestion { + margin: 0; + padding: 1rem 0; + color: #1a1a1a; + font-size: 1.05rem; + font-weight: 600; + cursor: pointer; + list-style: none; + display: flex; + align-items: center; + justify-content: space-between; + gap: 1rem; +} + +.faqQuestion::-webkit-details-marker { + display: none; +} + +.faqQuestion::after { + content: "+"; + flex: none; + color: #3b82f6; + font-size: 1.3rem; + font-weight: 400; + transition: transform 0.15s ease; +} + +.faqItem[open] .faqQuestion::after { + transform: rotate(45deg); +} + +.faqAnswer { + margin: 0.25rem 0 0; + color: #4b5563; + font-size: 1rem; + line-height: 1.65; +} + +.ctaRow { + margin-top: 0.25rem; +} + +.cta { + display: inline-block; + background: #3b82f6; + color: #ffffff; + border: none; + border-radius: 8px; + padding: 0.85rem 2.25rem; + font-size: 1rem; + font-weight: 600; + text-decoration: none; + box-shadow: 0 8px 24px -8px rgba(59, 130, 246, 0.45); + transition: + background 0.15s ease, + transform 0.15s ease; +} + +.cta:hover { + background: #2563eb; + transform: translateY(-1px); +} + +@media (max-width: 768px) { + .page { + padding: 2.5rem 1.25rem 4rem; + } + + .article { + gap: clamp(2.25rem, 8vw, 3rem); + } + + .headline { + font-size: 1.75rem; + } + + .stepCard { + flex-direction: column; + gap: 0.6rem; + } +} diff --git a/src/pages/guides/SplitStepAssembly.tsx b/src/pages/guides/SplitStepAssembly.tsx new file mode 100644 index 0000000..b60d4aa --- /dev/null +++ b/src/pages/guides/SplitStepAssembly.tsx @@ -0,0 +1,309 @@ +import type { ReactNode } from "react"; +import { Link } from "react-router-dom"; +import { Head } from "vite-react-ssg"; +import styles from "./SplitStepAssembly.module.css"; + +function ExternalLink({ + href, + children, +}: { + href: string; + children: ReactNode; +}) { + return ( + + {children} + + ); +} + +const WHY_REASONS = [ + "Quoting a single part — a supplier or machine shop only needs the one component you're sending out, not your entire 89-part assembly", + "3D printing one piece — you only want to print the bracket, not the whole mechanism it belongs to", + "Reusing a part — pulling one standard component out of an assembly to use in a new project", + "Sharing without exposing the whole design — sending a single part without handing over your full assembly", +]; + +const PAINFUL_WAYS: ReactNode[] = [ + <> + SolidWorks{" "} + requires manually converting each body into a component first — and it + commonly breaks on sheet-metal bodies with flanges + , + <> + + Siemens NX + {" "} + requires digging into the Export STEP dialog's Advanced tab and manually + enabling "External References" + , + <> + Third-party converters (like{" "} + + reaConverter + + ) can do it, but they're paid desktop software you have to install + , + 'None of the common free "online STEP viewers" actually offer this — most only let you look at the file, not pull parts out of it', +]; + +const HOW_TO_STEPS = [ + { + title: "Upload your assembly", + description: + "Go to cadviewer.xyz and drop in your assembly STEP file (or click to upload)", + }, + { + title: "Auto-detect the parts", + description: + "The viewer automatically detects it's a multi-part assembly and shows every component", + }, + { + title: "Disassemble the view", + description: + "Use the disassemble view to visually separate the parts from each other", + }, + { + title: "Select the part you need", + description: "Click the specific part you need", + }, + { + title: "Export it", + description: + "Download it — it exports as its own clean, standalone STEP file, ready to send anywhere", + }, +]; + +const FAQS = [ + { + question: "Is this actually free?", + answer: "Yes — no signup, no subscription, no watermark on exported files.", + }, + { + question: "Does it work with sheet-metal assemblies?", + answer: + "Yes — unlike the common SolidWorks workaround, sheet-metal bodies with flanges aren't a special case here.", + }, + { + question: "What file formats can I upload?", + answer: + "STEP, IGES, STL, OBJ, 3MF, BREP, and GLB. STEP and IGES are the ones that carry true assembly/part structure, so those are the best fit for this specific use.", + }, + { + question: "Do I need to install anything?", + answer: "No — it runs entirely in your browser.", + }, + { + question: "Is there a file size or part-count limit?", + answer: + "No fixed limit like most free viewers (which typically cap uploads at 200–300MB). Larger or more complex assemblies automatically switch to a lighter rendering mode to stay smooth, rather than rejecting the file outright.", + }, +]; + +const FAQ_JSON_LD = { + "@context": "https://schema.org", + "@type": "FAQPage", + mainEntity: FAQS.map((faq) => ({ + "@type": "Question", + name: faq.question, + acceptedAnswer: { + "@type": "Answer", + text: faq.answer, + }, + })), +}; + +export default function SplitStepAssembly() { + const earlySteps = HOW_TO_STEPS.slice(0, 4); + const laterSteps = HOW_TO_STEPS.slice(4); + + return ( + <> + + + How to Split a STEP Assembly Into Separate Part Files (Free, + Online) | CAD Viewer + + + + + + + + + + + + +
+
+
+ + ← Back to CAD Viewer + +

Guide

+

+ How to Split a STEP Assembly Into Separate Part Files (Free, + Online) +

+
+ +
+

+ No CAD software. No SolidWorks tricks. No install. +

+ +

+ If you've ever had an assembly STEP file with dozens of parts + and needed to send just one component to a machine shop, 3D + print a single bracket, or reuse one part in a different + design — you already know how annoying this usually is. Most + CAD software makes you fight through multi-step export + dialogs, and some (like SolidWorks) simply refuse to separate + sheet-metal bodies at all without a workaround. +

+ +

+ CAD Viewer does this in three clicks, for free, directly in + your browser. +

+ +
+ + Try it now — upload your STEP file + +
+
+ +
+

+ Why you'd need to do this +

+
    + {WHY_REASONS.map((reason) => ( +
  • + {reason} +
  • + ))} +
+
+ +
+

+ The usual (painful) ways +

+

+ Most CAD tools technically support this, but it's rarely + simple: +

+
    + {PAINFUL_WAYS.map((way, index) => ( +
  • {way}
  • + ))} +
+
+ +
+

+ How to do it with CAD Viewer +

+
    + {earlySteps.map((step, index) => ( +
  1. + {index + 1} +
    +

    {step.title}

    +

    + {step.description} +

    +
    +
  2. + ))} +
+ +
+ CAD Viewer showing a multi-part STEP assembly disassembled into separate components, with one part selected and ready to export as its own STEP file +
+ +
    + {laterSteps.map((step, index) => ( +
  1. + + {earlySteps.length + index + 1} + +
    +

    {step.title}

    +

    + {step.description} +

    +
    +
  2. + ))} +
+ +

+ That's it. No install, no account, no software license. +

+
+ +
+

Frequently asked

+
+ {FAQS.map((faq) => ( +
+ + {faq.question} + +

{faq.answer}

+
+ ))} +
+
+ +
+
+ + Try it now — upload your STEP file + +
+
+
+
+ + ); +}