Skip to content

Credit the parts library properly, add a licence, and rename to LDBuilder - #12

Merged
thebuilder merged 3 commits into
mainfrom
credit-the-library-and-rename-to-ldbuilder
Aug 28, 2026
Merged

thebuilder merged 3 commits into
mainfrom
credit-the-library-and-rename-to-ldbuilder

Conversation

@thebuilder

@thebuilder thebuilder commented Aug 28, 2026 •

Copy link
Copy Markdown
Owner

Started as "are there any legal issues with this project?" The answer was mostly no: the LEGO Fair Play disclaimer, the CCAL gate on OMR sets, and the preserved 0 Author: lines were all already right. Five things were not.

Attribution was wrong in four ways

All four came out of CAreadme.txt in the parts library rather than the summary page, which is less specific.

The licence version. The footer and README said CC BY 2.0. Every part that actually ships says CC BY 4.0 or CC BY 2.0 and CC BY 4.0; only the OMR models are CCAL 2.0, which the same document defines as a deprecated spelling of CC BY 2.0. So the credit named the wrong licence for most of the geometry on screen. Both are named now, and pnpm ldraw:pack writes credit lines to match.

No modification notice. CAreadme draws the derivative-work line in exactly the place this project sits on the far side of: a model that references library parts is not a derivative work, one that includes their source "in any form" is. Packing inlines part files, so every .mpd under public/ is a derivative, and CC BY asks a derivative to say it changed the work. Each packed root now carries a notice. Diffs on the packed files are +7 lines each and nothing else, which is the check that no geometry moved.

Placement took two tries and is the one subtle bit: the notice cannot go above the first 0 FILE, because LDrawLoader only treats that directive as the main model on line 0 and anything earlier demotes the whole model to an embedded file nothing references. It cannot go inside the header either, which is read positionally. It sits directly under the !LICENSE line it qualifies.

The viewer credited nobody. A deep link to /build/galaxy-explorer showed no sign of who built it, though the gallery card did. credit now rides on ModelData, so it travels with the model rather than being glued into the title string.

The exporter signed other people's work. Free build stamped 0 Author: LDraw Builder and a CCAL licence line onto the user's own model. Both are gone. That file also owes the library nothing: it references parts and embeds none, which is the case CAreadme names as not a derivative work.

No LICENSE at all

On a public repo that means all rights reserved, so nobody could legally fork it. A blanket licence would have been wrong too, since the packed .mpd files carry other people's CC BY work and are not ours to relicense. LICENSE is split: MIT for src/, scripts/, demo-models/ and root config, then the CC BY data called out path by path with which version applies and why it varies at 2023-03-05, the two OMR sets named with their authors, and a note that the MIT grant licenses neither trademark.

NOTICES.md covers dependencies and is generated by pnpm notices, because a notices file's only real failure mode is going stale when a dependency changes. Three things a hand-written one would have missed:

  • The inventory was machine-specific. Only this machine's prebuilt binaries install, so a notice generated on a Mac omits what a Linux deployment ships. Families come from the lockfile instead: 34 variants across three, of which 3 install locally. Siblings match on the stripped prefix rather than startsWith, or @img/sharp-* swallows @img/sharp-libvips-* and reports Apache-2.0 for ten LGPL packages.
  • libvips is LGPL-3.0-or-later, the only copyleft in the tree, so it gets its own section. The claim that nothing imports next/image is checked with git grep at generation time rather than asserted, so it cannot rot.
  • caniuse-lite is CC-BY-4.0 and needs attribution like the parts library does.

The rename

Quality, Brand, and the LDraw Name says LDraw "should not appear in a program's title and/or URL", and that LDraw.org cannot grant an exception because it licenses the mark from the Jessiman Estate. It suggests an LD prefix, which is where LDView and LDCad get their names. The README records that reasoning next to the trademark notice so it does not get reverted as a typo later. The packed-file notice deliberately carries no tool name, so it did not have to change.

Repairs this needed along the way

  • pnpm ldraw:palette was broken on main, passing index where packModel wants resolve, so it could not run at all. That blocked repacking the palette, which inlines 642 part files and needs the notice as much as a model does.
  • jsdom was declared but not installed, so 10 test files silently never ran and pnpm test reported 354 passing. The real number was 543 before this branch, 592 after.
  • disposeModel had no tests. Worth fixing for its own sake: nothing observable goes wrong when teardown is incomplete, it just leaks a few hundred megabytes per model opened.

For the reviewer

  • Rebased onto 05d1d17. The three upstream commits touched nearly every file here, so conflicts were resolved rather than merged blindly: the redesigned favicon and the tightened README wording are kept, only the name changed; the deleted wall demo stays deleted and the manifest was regenerated rather than hand-merged.
  • Every commit passes pnpm check on its own, not just the branch head.
  • pnpm run audit passes with no introduced findings. Getting there moved the notices rules into scripts/lib/notices.mjs, pure and tested, with the CLI as the I/O half. That matches how ldraw-pack and omr-index are already split and is what lets the audit see the coverage.
  • Verified in a browser, not just in tests: the footer, the gallery credits, the viewer's "Built by" line, and the free-build page loading the repacked palette.

On the wordmark, raised and settled. I earlier reported finding no wordmark; that was wrong. page.tsx puts three squares in LEGO's primaries beside the title, and main has since folded the same three colours into the favicon. Raised because it is the closest thing to a trade-dress question left in the project. Deliberately keeping it: with the name no longer echoing LEGO or LDraw, and a Fair Play disclaimer on every route of a non-commercial project, the palette on its own is not what creates the risk. Recorded here so it reads as a decision rather than an oversight, and so anyone reopening it starts from the reasoning instead of the colours.

The attribution was wrong in four ways, all of them found by reading
CAreadme.txt in the library rather than the summary page.

Name both licence versions. Every part that ships carries CC BY 4.0 or
"CC BY 2.0 and CC BY 4.0"; only the OMR models are CCAL 2.0, which the
same document defines as a deprecated spelling of CC BY 2.0. Crediting
only 2.0 named the wrong licence for most of the geometry on screen.

Say the models were modified. CAreadme draws the derivative-work line in
exactly the place packing sits on the far side of: a model that
references library parts is not a derivative, one that includes their
source "in any form" is. Every packed root now carries a notice saying
what packing did and what it left alone. It goes under the header rather
than above it, because LDrawLoader only treats "0 FILE" as the main
model when it is on line 0, and a header is read positionally.

Credit the model's author in the viewer, not just the gallery. A deep
link to /build/galaxy-explorer showed no sign of who built it. Credit
now rides on ModelData, so it travels with the model instead of being
glued into the title string.

Stop signing other people's work. A free build is the person's own
model, so the exporter no longer stamps it "0 Author: LDraw Builder" or
licenses it on their behalf. It owes the library nothing either: the
file references parts and embeds none, which CAreadme names as the case
that is not a derivative work.

Two repairs the above needed. pack-palette passed `index` where
packModel wants `resolve` and so could not run at all, which blocked
repacking the palette; it inlines 642 part files and needs the notice as
much as a model does. And disposeModel had no tests, which is worth
fixing for its own sake: nothing observable goes wrong when teardown is
incomplete, it just leaks a few hundred megabytes per model opened.
"Quality, Brand, and the LDraw Name" says LDraw "should not appear in a
program's title and/or URL to protect the uniqueness of the LDraw
trademark", and that LDraw.org cannot grant an exception because it
licenses the mark from the Jessiman Estate rather than owning it. It
suggests an LD prefix instead, which is where LDView and LDCad get their
names.

"LDraw Builder" at github.com/thebuilder/ldraw-builder was outside that
on both counts. The README records the reasoning next to the trademark
notice, so this does not get quietly reverted as a typo later.

The packed-file notice deliberately carries no tool name, so it did not
have to change here.
There was no LICENSE at all, which on a public repo means all rights
reserved: nobody could legally fork it. A single blanket licence would
have been wrong too, because the packed .mpd files under public/ carry
other people's CC BY work and are not ours to relicense.

So LICENSE is split. MIT for src/, scripts/, demo-models/ and the root
config; then the CC BY data called out path by path, with which version
applies and why it varies at 2023-03-05, the two OMR sets named with
their authors, and a statement that the packed files are modified and
how. It also says plainly that the MIT grant covers copyright in the
code and licenses neither trademark.

NOTICES.md covers the dependencies, generated by `pnpm notices` rather
than written by hand. A notices file's only real failure mode is going
quietly stale when a dependency changes, and this repo already generates
and commits colors.generated.ts, omr-index.json and the packed models
for that reason. Now a diff in NOTICES.md is the honest answer to
whether the obligations moved.

Three things a hand-written file would have missed:

The inventory was machine-specific. Only this Mac's prebuilt binaries
install here, so a notice generated on a Mac omits what a Linux
deployment ships. The families are read out of the lockfile instead: 34
variants across three, of which 3 install locally. Siblings match on the
stripped prefix rather than startsWith, or @img/sharp-* swallows
@img/sharp-libvips-* and reports Apache-2.0 for ten LGPL packages.

libvips is LGPL-3.0-or-later, the only copyleft in the tree, so it gets
its own section instead of one row among thirty. It arrives under sharp,
which serves next/image; the claim that nothing imports next/image is
checked with git grep at generation time rather than asserted, so it
cannot rot silently.

caniuse-lite is CC-BY-4.0 and needs attribution like the parts library
does.

The rules live in scripts/lib/notices.mjs, pure and tested, with the CLI
as the I/O half. That is how ldraw-pack and omr-index are already split,
and it is what lets the audit see the coverage.
@vercel

vercel Bot commented Aug 28, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
ldbuilder Ready Ready Preview Aug 28, 2026 11:22am

@thebuilder
thebuilder marked this pull request as ready for review August 28, 2026 11:26
@thebuilder
thebuilder merged commit 17c6830 into main Aug 28, 2026
3 checks passed
@thebuilder
thebuilder deleted the credit-the-library-and-rename-to-ldbuilder branch August 28, 2026 11:26

This branch was successfully deployed

1 active deployment
Preview — 78270de5 Deployed Aug 28, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant