This guide covers local setup, catalog generation, preview assets, validation, and deployment details for step.parts.
Use Node.js 22.5 or newer. The repo includes .nvmrc, so nvm use will select the same major version used by CI.
npm install
npm run devOpen http://localhost:3000.
For scripted additions, pass catalog metadata as flags:
npm run catalog:add -- \
--step /path/to/iso4762_m3x12.step \
--name "ISO 4762 socket head cap screw, M3 x 12" \
--category fastener \
--family socket-head-cap-screw \
--tag screw \
--tag socket-head \
--tag metric \
--alias "SHCS M3x12" \
--standard "ISO 4762" \
--attr thread=M3 \
--attr lengthMm=12 \
--attr driveStyle=hex-socketUse --dry-run before writing files when metadata is uncertain.
The human-authored catalog is catalog/parts.json. It contains only semantic fields:
id: stable snake_case ASCII identifiernameanddescription: searchable human-readable textcategory: kebab-case broad group such asfastener,actuator, orelectronicsfamily: optional but strongly encouraged kebab-case product/part family used for faceting and related grouping when a natural grouping exists. Examples:socket-head-cap-screw,deep-groove-ball-bearing,t-slot-extrusion,damiao,feetech,raspberry-pi, orarduino.tags: supplemental lowercase kebab-case discovery labels for reusable type, function, material, interface, or feature concepts. Do not duplicate category, family, standard, aliases, model/SKU values, dimensions, manufacturer names, or provenance.aliases: alternate lookup terms, abbreviations, and compact namesstandard: optional{ body, number, designation }stepSource: optional direct live STEP/STP file URL for branded productsproductPage: optional sales, product, documentation, or support page for a branded productattributes: part-specific scalar facts such asthread,lengthMm,material, orslotSizeMm
Reserve stepSource and productPage for branded products with official source or product pages.
See TAGGING.md before adding or reviewing tags. Catalog files live together under catalog/:
catalog/parts.json: human-authored source catalogcatalog/parts.sqlite: generated catalog metadata consumed by the appcatalog/taxonomy.json: guardrails for rigid, repeatable families such as standardized fasteners, washers, bearings, stock, and helper geometrycatalog/step/{id}.step- local generated previews under
public/glb/andpublic/png/are ignored by Git and published to Vercel Blob
catalog/taxonomy.json is intentionally narrow. Use it when a family has predictable identity fields and required attributes, such as thread plus lengthMm for screws or profile dimensions for stock. Do not add flexible brand, product, or one-off families just to make the taxonomy exhaustive; use existing examples in catalog/parts.json and the SQLite search API for those.
Generated catalog rows add stable asset URLs, STEP byte size, and STEP SHA-256 checksum. Refresh SQLite without rebuilding preview assets:
node scripts/generate-catalog.mjsWhen local preview assets need to be inspected or repaired, run the catalog asset build. Each selected STEP part is processed as a GLB/PNG pair, and SQLite is not modified.
Use STEP_PARTS_EXPORT_CONCURRENCY to tune paired export lanes; it defaults to 2. Use --targets to build specific outputs:
npm run catalog:build -- --force-build
npm run catalog:build -- --targets public/glb/raspberry_pi_5.glb,public/png/raspberry_pi_5.pngFor large batches, put targets in a newline-delimited file. Blank lines and lines beginning with # are ignored. Entries can be part ids, bare filenames, absolute or relative paths, or catalog/step/{id}.step paths:
find catalog/step -name '*.step' > /tmp/changed-steps.txt
npm run catalog:build -- --targets-file /tmp/changed-steps.txt
npm run catalog:build -- --targets @/tmp/changed-steps.txtFull metadata rewrites belong to node scripts/generate-catalog.mjs.
Verify that committed generated files and assets are current without rewriting anything:
npm run catalog:checkThe app serves GLB and PNG preview URLs from Vercel Blob. In local dev, generated previews in public/glb/ and public/png/ take priority when present; missing local preview files fall back to the public step.parts Blob origin by default. Set STEP_PARTS_BLOB_BASE_URL locally only when you need to override that origin. The local preview directories are ignored and should not be committed.
After rebuilding previews, publish them to Blob:
BLOB_READ_WRITE_TOKEN=... npm run catalog:sync-assetsThe sync command uploads immutable public assets at preview/glb/{id}-{stepSha256}.glb and preview/png/{id}-{stepSha256}.png. Set STEP_PARTS_BLOB_BASE_URL in production to the printed https://...public.blob.vercel-storage.com origin so API records can return direct Blob URLs.
The public API lives under https://api.step.parts/v1. All /v1 responses include permissive CORS headers for external tools and agents.
GET /v1/parts returns catalog freshness metadata, items, pagination metadata, active filters, and facet counts. Unfiltered results start with a fixed 100-part showcase, then continue in stable source catalog order. Filtered results are ordered by stable source catalog order. Facet counts are global unless a category is selected; then tag, family, and standard facets are scoped to the selected categories while category options stay global.
Query parameters:
q: metadata search across names, tags, aliases, standards, product/source URLs, and attributestag: repeated supplemental tag filter for reusable type, function, material, interface, or feature labelscategory,family,standard: repeated filters for dedicated metadata fieldspage: 1-based page numberpageSize: API requests default to 100 and are capped at 500; the web directory defaults to 100
Additional machine-readable surfaces:
https://api.step.parts/v1/openapi.json: OpenAPI 3.1 contract for the query API, single-part lookup, compact index, and schema endpointhttps://api.step.parts/v1/catalog/schema: JSON Schema plus field definitions, filter semantics, result ordering, and per-family attribute definitionshttps://api.step.parts/v1/catalog/parts.index.json: compact id/name/facet discovery index for cheap agent lookups before fetching detailshttps://api.step.parts/v1/parts/{id}: single-part lookup with absolutepageUrl,apiUrl,glbUrl,pngUrl, and environment-awarestepUrl
Common agent lookups:
- Resolve aliases:
https://api.step.parts/v1/parts?q=SHCS - Search attribute keys and values:
https://api.step.parts/v1/parts?q=lengthMm%2012 - Find ISO 4762 socket head cap screws:
https://api.step.parts/v1/parts?category=fastener&family=socket-head-cap-screw&standard=ISO%204762 - Fetch one part and then download its STEP file from
stepUrl:https://api.step.parts/v1/parts/din913_set_screw_m3x3
npm run checknpm run check runs the non-mutating catalog check, ESLint, and a production build. For faster local commit checks, install the repository hook once:
npm run hooks:installThe pre-commit hook runs npm run check:commit, which verifies generated catalog/assets and linting without the slower production build. GitHub Actions runs npm run check:pr on pull requests without LFS hydration, and npm run check:main on pushes to main with changed STEP-content validation.
STEP/STP assets in catalog/step are tracked by Git LFS through .gitattributes. GLB/PNG previews are Vercel Blob assets and are not committed. CI and Vercel deployments are configured not to download LFS objects for now, so full catalog validation and preview asset generation are manual/local operations.
Canonical STEP files live in catalog/step so local development and catalog validation read the same files used to generate catalog/parts.sqlite. Production STEP URLs use GitHub LFS media instead of deployed static files. By default production uses VERCEL_GIT_COMMIT_SHA, falling back to main; set STEP_PARTS_GITHUB_REF to override the ref, and set STEP_PARTS_GITHUB_REPOSITORY or STEP_PARTS_GITHUB_OWNER plus STEP_PARTS_GITHUB_REPO to override the repository. Set STEP_PARTS_STEP_ASSET_MODE=local only for a production-like local run that should serve checked-out STEP files directly.
See .env.example for the supported deployment environment variables.
Set NEXT_PUBLIC_SITE_URL=https://www.step.parts and NEXT_PUBLIC_API_URL=https://api.step.parts in Vercel, then add www.step.parts and api.step.parts as domains on the same project. The api.step.parts domain serves the /v1 API routes; the app's CORS headers allow browser and non-browser clients to call them directly.