DEV Community

TANCYBOX
TANCYBOX

Posted on

When a Product Isn't a Box: Modeling Curved Packaging as Data

Last time I wrote about modeling a custom physical product as a JSON spec. Everything in that schema quietly assumed a rectangular object: width, height, depth, a tolerance, and corners.

Then a real product arrived that broke all of it — an egg-shaped wine case. No corners, no flat faces, and no obvious "width".

Here's what a curved product exposes about a data model, and how to handle it.

Oval oak wine case

Where the rectangular assumption breaks

The original type was:

type Dimensions = { widthMm: number; heightMm: number; depthMm: number };
Enter fullscreen mode Exit fullscreen mode

For a box, that is complete. For an oval case:

  • width/height/depth still describe the bounding envelope, but not the form
  • the front is a curved surface with a cut-out aperture
  • the interior is profiled to the bottle's shoulder, not a rectangle
  • tolerance applies to a curve, not to an edge

The moment you need to quote tooling for this, the schema is visibly under-specified.

The fix: separate envelope from profile

Keep the bounding box — it is still useful for volume and shipping — and add a profile describing the actual cross-section:

type Profile =
  | { kind: 'rect'; cornerRadiusMm?: number }
  | { kind: 'ellipse'; rxMm: number; ryMm: number }
  | { kind: 'bezier'; controlPoints: readonly [number, number][] };

type Dimensions = {
  envelope: { widthMm: number; heightMm: number; depthMm: number };
  profile: Profile;
  toleranceMm: number;
};
Enter fullscreen mode Exit fullscreen mode

Now "oval" is data, not a sentence in an email thread.

Three fields a curved case adds

type CurvedCaseExtras = {
  orientation: 'upright' | 'lying';
  aperture?: {
    shape: 'ellipse';
    rxMm: number;
    ryMm: number;
    frameWidthMm: number;
  };
  interiorProfile: 'flat' | 'profiled';
};
Enter fullscreen mode Exit fullscreen mode

Why each one exists:

  1. orientation — a standing oval has an "up" axis. It changes how the case is tooled and how it sits in a shipping carton.
  2. aperture — the window cut into the face. For a plain box this is zero. Here it is a core design element, and it creates a fabrication step of its own.
  3. interiorProfile — the inner cutout follows the product's contour. "Does the bottle fit" stops being a boolean and becomes a curve-fit question.

The case open, showing the profiled interior

The general lesson

Physical products do not fit a schema designed for cardboard boxes. The fix is not a bigger schema — it is separating what is universal from what is shape-specific:

  • Universal: quantity, tolerance, finish, branding, lead time
  • Shape-specific: envelope + profile + aperture + interior

You get the universal part right once. The shape-specific part you extend per product family, instead of bolting on fields until the model collapses.

Takeaway

If your product data is a width/height/depth triple and nothing else, it works fine — until the first non-rectangular product arrives. Add a profile before that happens, and keep the envelope for everything that genuinely only cares about size.


The curved case in this article is a real product from TANCYBOX, a packaging manufacturer — the schema gaps came from actually having to quote it.

Top comments (0)