Files

15 KiB
Raw Permalink Blame History

Parts Drawer Labels

Admin-only labelling system for sorting drawers and bags. Browse a part taxonomy, define a label per drawer, and print them onto sticker sheets, continuous tape, or Dymo die-cut stock.

Lives at /admin/labels — in the admin menu as Parts Labels.


Deploying

The feature is already wired into app/__init__.py, schema_upgrade.py and base.html, so a normal pull is enough:

git pull

Restart LIM. The tables are created automatically at boot by app/services/schema_upgrade.py, and the taxonomy seeds itself the first time an admin opens the page.

If you'd rather make the database change deliberately before restarting:

python migrate_add_part_labels.py
python migrate_add_parts_catalogue.py

Optional extras:

What Why How
Rebrickable API key Part photos when importing a label REBRICKABLE_API_KEY=... in .env, or paste it into Labels → Settings
ReportLab PDF export button for sheets pip install reportlab
A font Readable labels apt install fonts-dejavu-core, or LABEL_FONT=/path/to.ttf

The font is not optional, and it is the one that bites. Pillow draws with a built-in 10-pixel bitmap font when it can't find a real one, and that font ignores the size asked for: labels come out with letters under a millimetre tall — fine on screen, unreadable on the sticker. python:3.12-slim, which the Dockerfile is built on, ships no fonts at all, so the image now installs fonts-dejavu-core. Rebuild the image after pulling. If you run LIM outside Docker, install any sans font or point LABEL_FONT at a .ttf. Labels → Settings → Label font says which one is actually in use.

Neither is required. Without them you type labels in by hand, upload your own images, and print from the browser. The part catalogue works without a key.


Why not Brickset?

Brickset's API v3 covers sets, minifigs and instructions. It has no parts endpoint, so it can't supply part numbers, names or part images. Rebrickable can, and a key is free. Brickset stays where it is, doing sets.

Why not Brick Architect's labels?

Tom Alphin's label PDFs and his category numbering are his own copyrighted work. This feature doesn't scrape, copy or redistribute them. What ships is a starter taxonomy built from standard LEGO/BrickLink part terminology, arranged in the same style of hierarchy, and completely editable — rename, renumber, recolour and restructure it from Labels → Categories so it matches how your drawers actually run. If you want his exact labels, download them from his site and use them; this is for generating your own.


Day-to-day

Adding labels

  • New Label — name, dimensions, part number, alternates, category, drawer, colour, image.
  • Or pick them off the Part Catalogue tab (see below), which is much faster for more than a handful.
  • Or, with a Rebrickable key, use the quick lookup box on the labels page.

The name + dimensions split matters. Name is the big bold line ("Brick", "Plate, Modified with Clip"); dimensions is the geometry ("2 x 4"). They're printed together but stored apart so you can turn dimensions off for mixed drawers.

Alternate part numbers are for old moulds that live in the same drawer — 3001a, 3001b. Comma separated, searchable, optionally printed.

Printing to sheets

  1. Tick labels (or Print whole category), press Sheet.
  2. Pick a sheet, set the options, hit Update preview.
  3. Print from the browser: margins None, scale 100% — not "Fit to page", which is what ruins most label sheets.

Options worth knowing:

  • Skip positions — start partway down a part-used sheet instead of wasting it.
  • Copies each — same label on several drawers.
  • Offset X/Y — per-printer alignment nudge in millimetres. Set your usual value once in Settings.
  • Outline each label — hairlines for cutting, and for test-printing on plain paper before you commit a sheet of Averys.
  • Show on each label — image, name, dimensions, part number, alternates, category, category code, drawer, colour, category colour stripe.

Sheet presets: Avery L7651 (65/sheet, good for bags), L7160 (21/sheet, the all-rounder), L7163 (14/sheet, wide), L7159 (24/sheet), L7169 (8/sheet, large), Avery 5160 (US Letter), plus two plain-A4 grids for cut-your-own sticker paper or paper-and-tape.


The part catalogue (the Update button)

Labels → Part Catalogue, then Update catalogue.

This pulls Rebrickable's published catalogue dumps into a local table so that making a label is picking a part off a list rather than typing it out:

https://cdn.rebrickable.com/media/downloads/part_categories.csv.gz
https://cdn.rebrickable.com/media/downloads/parts.csv.gz

Two gzipped CSVs, about 60,000 parts, regenerated monthly by Rebrickable and free to use with a credit. No API key is needed for this — the key only adds the real part photo at the moment a catalogue row becomes a label.

The sync runs on a background thread and reports progress to the page, so you can close the tab. Re-running it is cheap and idempotent: it only writes rows that are new or actually changed (a second run on an unchanged catalogue writes nothing).

Category mapping. Rebrickable's categories are theirs; the drawer taxonomy is yours. Open a Rebrickable category and set "Parts in this category become labels in …" once, and from then on importing any part from it drops the label straight into the right drawer group. Unmapped categories just ask you each time.

Making labels. Tick parts, optionally override the drawer category, press Make labels. Parts already labelled are flagged and skipped, so you can re-import a category without creating duplicates. Brick 2 x 4 is split into name Brick + dimensions 2 x 4 on the way in, because the label stores them separately so the print options can show or hide the geometry.

Thumbnails in the browse list use Rebrickable's predictable LDraw render path and quietly disappear for parts that have no LDraw model. That is expected — the real image is fetched per-part when you create the label.


Printing to the Brother VC-500W

Labels → tick some labels → Tape, or the tape icon on any row.

The VC-500W is AirPrint-enabled, which means it speaks IPP on port 631 — an open, documented protocol. So LIM talks to it directly over the network: no Brother driver, no P-touch Editor, no exporting a PDF and printing it by hand. Brother publish no raw command protocol for this printer and none is reverse-engineered here; it is plain standard IPP (RFC 8010/8011).

Setup. Put the printer's IP address into Labels → Settings → Tape printer. Give it a DHCP reservation first or the address will wander. Then hit Test connection on the tape page: it reports the model, state, and exactly which document formats the printer will accept.

Format negotiation. LIM renders at the printer's native 313 dpi and sends whichever format the printer lists that LIM can produce — JPEG, PNG or PDF, in that order. If your firmware only offers image/urf or raster formats, the test will say so and you use Download PDF instead. You can pin a format in Settings if auto-negotiation ever picks wrong.

Tape widths. CZ tape in 9, 12, 19, 25 and 50 mm. Each preset knows its printable width; labels are sized to the content, or to a fixed length if you set one. Maximum length is about 430 mm.

Check this on your first print: labels are rotated 90° by default, because the tape feeds lengthwise. If your first one comes out sideways, untick Rotate for tape feed and print again. It is the one setting worth testing on a fresh printer, so print one before queueing fifty.

Copies are sent as repeated jobs rather than via the IPP copies attribute, because tape printers vary wildly in whether they honour it.

One job at a time. The VC-500W prints at about 7.5 mm/s and accepts a single job at a time: anything that arrives while the tape is still moving comes back server-error-busy, which is why firing a batch at it used to print the first label and fail the rest. LIM now waits for the printer to report idle before each job and retries while it reports busy, so a batch goes through in order. The trade is that printing is synchronous — a long run holds the page until it finishes. Don't refresh mid-run, or you'll send the batch twice and spend the tape twice.

Combining parts onto one label

Under the preview: tick two or more labels and press Combine onto one label. Split apart undoes it for the ticked ones, and Back to drawers throws the manual grouping away and goes back to grouping on the drawer field.

Automatic grouping matches on the drawer / location field, which is what you want for a sorted drawer. Combining by hand is for everything that has nothing in common to match on — a custom build, a MOC bag, the odds and ends tray.

A hand-made group is never broken up: it is kept whatever Size says, and the label grows 5 mm for each part past the second (two parts 20 mm, three 25 mm, four 30 mm). The grouping lives in the URL, so it survives printing and you can bookmark a set of combined labels.

Text size

Tape & layout → Text size, 0.5× to 2×, with Normal / Large / Largest presets and a slider. The same control is on the Dymo page.

The name is sized first and everything else gives way to it: the part image shrinks (and is dropped entirely if that is what it takes) before the type does. The whole name always prints — it wraps to two lines and settles at the largest size that fits.

40mm is 40mm. Once the name spans the label, turning the dial further changes nothing, and most names reach that by about 1.4×. What the setting really buys you is the trade against the artwork: with a part image on the label, 1.4× roughly halves the picture and makes the name half again as big. Untick Part image to give the text the whole width from the start.

What to do when it won't print

Symptom Likely cause
Could not reach the printer Wrong IP, printer asleep, or on its own ad-hoc Wi-Fi rather than your LAN
Printer rejected the job: …not-supported It won't take JPEG/PNG/PDF. Use Download PDF
Prints sideways Untick Rotate for tape feed
Text clipped at the edges Raise Padding, or lower Text size
Blank or faint Cleaning cassette (CK-1000), or the tape is in backwards
Printer stayed busy after 6 attempts Something else is printing to it, or a job is stuck. Power-cycle the printer
Text smaller than you asked for A long name fits at that size and no larger. Untick Part image, or shorten the name
Text tiny and unreadable on every label No font on the server. Install fonts-dejavu-core and restart; check Settings → Label font
Printed labels look furry or broken up Dymo Ink set to Dithered; use Crisp for text

Printing on a Dymo LabelWriter

Labels → tick some labels → Dymo, or the sticker icon on any row.

Tape is a roll; a LabelWriter is die-cut stock — one fixed rectangle at a time. A 40 × 15mm drawer label is small enough that several fit on one sticker, so LIM gangs them up with dashed cut guides and gives you a PDF. Print, cut, stick. The labels are drawn by the same code as the tape ones, so a drawer labelled from the Dymo looks identical to one off the VC-500W.

Stock presets (Dymo's own part numbers and sizes):

Stock Size Standard labels per sticker
99014 shipping 101 × 54mm 6 (2 across, 3 down)
30256 shipping 59 × 102mm 5 (1 across, 5 down)
1744907 (4XL, 4 × 6in) 104 × 159mm 18
99012 address 89 × 36mm 4
99010 address 89 × 28mm 2

Labels per sticker is auto by default — as many as physically fit — or pin it to 4-up (2 × 2), 6-up (2 × 3) or one at a time. A two-part drawer label is 20mm instead of 15, so a mixed run fits fewer; labels stack down a column and then across, which wastes less of the sticker than filling it in rows.

Printing. Each PDF page is exactly the stock size, so set the Dymo driver to that label and print at 100% / Actual size — never "Fit to page", which quietly shrinks the 40mm labels by a few percent. There is no direct network printing here because the LabelWriter 4XL is a USB printer; the PDF goes through whatever driver the machine already has.

It is a thermal printer, so there is no colour and no greys of its own: each dot is burnt or it isn't. LIM reduces the page itself rather than leaving it to the driver, whose halftoning turns 2mm letters to mush. Ink:

  • Crisp black and white (the default) — thresholded, so letters have hard edges and part photos become silhouettes. The PDF comes out as lossless CCITT G4, a few kilobytes a page.
  • Dithered — Floyd-Steinberg, which keeps photographic shading at the cost of speckling the type.
  • Leave in colour — for printing the same PDF on an inkjet or laser.

Category colour stripes print as black bars either way.

Other options worth knowing: Skip slots starts partway into a part-used sticker, Margin keeps ink off the die-cut edge where feed tolerance lives, Gap is cutting room between labels, and Copies each repeats every label.

Set the stock you usually keep loaded in Labels → Settings → Dymo LabelWriter and the page starts there.


The catalogue look

The labelling pages use a denser, cooler-toned skin than the rest of LIM (app/static/css/labels-bricklink.css, scoped to .bl). That is deliberate: this is a reference catalogue where you scan hundreds of rows, not a library you browse by cover art — so small type, tight rows, thin rules and counts on everything. It is our own stylesheet, not a copy of anyone's site, and it does not leak into the red LEGO-themed pages.


Where things live

app/models/part_label.py            PartCategory (tree) + PartLabel
app/models/part_catalog_item.py     local Rebrickable mirror + sync history
app/services/part_catalog.py        taxonomy seeding, Rebrickable API client
app/services/catalog_sync.py        the Update button: CSV dumps -> database
app/services/label_render.py        sheet geometry, layout, optional PDF
app/services/tape_printer.py        313dpi tape rendering, CZ tape presets
app/services/ipp_client.py          minimal IPP client (RFC 8010/8011)
app/routes/labels.py                /admin/labels (all admin_required)
app/routes/labels_catalog.py        /admin/labels/catalog
app/routes/labels_tape.py           /admin/labels/tape
app/services/dymo_sheet.py          Dymo stock presets, ganging, 300dpi PDF,
                                    thermal ink reduction
app/routes/labels_dymo.py           /admin/labels/dymo
app/data/part_taxonomy.json         the starter taxonomy
app/static/css/labels-bricklink.css the catalogue skin
app/templates/admin/labels/         index, form, categories, settings, print,
                                    catalog, tape, dymo, _nav
<UPLOAD_FOLDER>/parts/              cached and uploaded part images

Labels are not an inventory. There's no quantity field on purpose — the drawer tells you how many you have.


Created by: Jess Rogerson (yelling commands at Claude.AI)