# Designs & transforms > How artwork is placed on a print area — layers, the position (transform) model with a worked example, defaults and resolution checks. Source: https://swaglists.com/docs/designs A **design** puts one or more artwork layers on a [placement](https://swaglists.com/docs/catalog.md#placements). Designs are part of [products](https://swaglists.com/docs/products.md) (and of order items with [inline designs](https://swaglists.com/docs/personalized-orders.md)): ```json { "designs": [ { "placement": "front", "layers": [ { "file_id": "file_01k8x3y1q3w5e7r9t1y3u5i7o9", "position": { "x": 0.1667, "y": 0.05, "width": 0.6667, "height": 0.5556, "rotation": 0 } }, { "url": "https://cdn.example.com/badge.png", "opacity": 0.9 } ] } ] } ``` - One entry per placement (`placement` = the placement `key`), up to 20 layers each, drawn bottom to top. - Each layer references an uploaded file (`file_id`) **or** a public image `url` that we download for you. - `position` (alias `transform`) places the layer; omit it to center the artwork and fit it inside the area. - `opacity` is 0–1 (default 1). We generate the print-ready file for production ourselves, at the exact size the product needs, from your artwork and these positions — so you only ever think in fractions of the print area. ## The position model Positions are **fractions of the print area**, measured from its top-left corner: ```text (0,0) ─────────────────── x ───────────────────► (1,0) │ print area (the placement) │ │ x = 0.1667 │ ├─────┐ │ ┌──────────────────────┐ ┬ y = 0.05 │ │ │ │ y │ artwork │ │ height = 0.5556 │ │ │ │ │ └──────────────────────┘ ┴ │ ├──── width = 0.6667 ───┤ ▼ (0,1) (1,1) ``` | Field | Meaning | | --- | --- | | `x` | Left edge of the artwork box, as a fraction of the print area **width**. | | `y` | Top edge of the artwork box, as a fraction of the print area **height**. | | `width` | Width of the artwork box, as a fraction of the print area width. | | `height` | Height of the artwork box, as a fraction of the print area height. | | `rotation` | Degrees, clockwise, around the center of the artwork box (default 0). | - `x`/`y` describe the **un-rotated** box; rotation turns it around its center. - Values outside 0–1 are allowed (up to ±10) for intentional bleed: whatever falls outside the area is cropped. A layer entirely outside gets a `layer_outside_area` warning; if no layer is visible the design is rejected (`design_not_visible`). - The artwork is scaled to fill the box exactly. **To avoid stretching, keep the box's aspect ratio equal to the artwork's** (see below). ### Keeping the aspect ratio Because `width` and `height` are fractions of different lengths, the box's real aspect ratio is: ```text box aspect = (width × area_width) ÷ (height × area_height) = (width ÷ height) × placement.aspect_ratio ``` So for artwork of `art_w × art_h` pixels, choose a `width` and compute: ```text height = width × placement.aspect_ratio × art_h ÷ art_w ``` ## Worked example A tee's `front` placement is **15 × 18 in** (`aspect_ratio` 0.8333, recommended 4500 × 5400 px). Your logo is a **3000 × 3000 px** PNG. You want it **10 in wide**, centered horizontally, **0.9 in** below the top of the print area. 1. `width` = 10 in ÷ 15 in = **0.6667** 2. `height` = 0.6667 × 0.8333 × 3000 ÷ 3000 = **0.5556** (= 10 in ÷ 18 in, so the logo stays square) 3. `x` = (1 − 0.6667) ÷ 2 = **0.1667** (centered) 4. `y` = 0.9 in ÷ 18 in = **0.05** 5. Effective DPI = 3000 px ÷ 10 in = **300 DPI** ✓ ```json { "x": 0.1667, "y": 0.05, "width": 0.6667, "height": 0.5556, "rotation": 0 } ``` Without a `position`, the same logo would get the default **contain & center** position — as large as possible inside the area, centered: ```json { "x": 0, "y": 0.083333, "width": 1, "height": 0.833333, "rotation": 0 } ``` That prints it 15 in wide (3000 px ÷ 15 in = 200 DPI — fine, above the 150 DPI warning threshold). ```js title="Node.js" // Position for artwork `artW × artH` px, `widthIn` inches wide, centered, `topIn` inches from the top. function position(placement, artW, artH, widthIn, topIn = 0) { const width = widthIn / placement.width_in; const height = width * placement.aspect_ratio * (artH / artW); return { x: (1 - width) / 2, y: topIn / placement.height_in, width, height, rotation: 0 }; } // position({ width_in: 15, height_in: 18, aspect_ratio: 15 / 18 }, 3000, 3000, 10, 0.9) // → { x: 0.1667, y: 0.05, width: 0.6667, height: 0.5556, rotation: 0 } ``` ```python title="Python" def position(placement, art_w, art_h, width_in, top_in=0.0): width = width_in / placement["width_in"] height = width * placement["aspect_ratio"] * art_h / art_w return {"x": (1 - width) / 2, "y": top_in / placement["height_in"], "width": width, "height": height, "rotation": 0} ``` ## Resolution checks When you create or update a product we compute each layer's effective DPI from the placement size and the layer's size: - below **150 DPI** (or the placement's `min_dpi`, if higher): the product is created with a `dpi_low` [warning](https://swaglists.com/docs/errors.md#warnings) — it may print slightly soft; - below **75 DPI**: the request fails with [`artwork_resolution_too_low`](https://swaglists.com/docs/errors.md#artwork_resolution_too_low). Use a larger image or place it smaller. Warnings are returned in the product response's `warnings` array (`code`, `message`, `param`, `placement`, `effective_dpi`). ## Tips for great prints - Export artwork at the placement's `recommended_width_px` × `recommended_height_px` (300 DPI) and position it with fractions — never upscale small images. - Use PNG with a transparent background; anything transparent is not printed (the garment color shows). - Keep important content away from the very edges of the area. - Embroidery placements need simple shapes and few colors; check the placement `technique`. - Changing designs later (`PATCH /products/{id}` with `designs`) re-renders mockups; existing orders keep the designs they were created with.