Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/PloutusLab/krafta-web/llms.txt

Use this file to discover all available pages before exploring further.

Each product variant in Krafta has exactly one PrintTemplate record that serves as the contract between the product catalog and the design editor. The template tells the Fabric.js canvas where to position the customer’s artwork on the product mockup, what shape to clip it to, and what minimum resolution to enforce before the design can be submitted to production.

PrintTemplate model fields

model PrintTemplate {
  id              String         @id @default(uuid())
  variantId       String         @unique
  mockupImageUrl  String
  printAreaX      Decimal        // Percentage (0–100) from left edge of mockup
  printAreaY      Decimal        // Percentage (0–100) from top edge of mockup
  printAreaWidth  Decimal        // Percentage (0–100) of mockup width
  printAreaHeight Decimal        // Percentage (0–100) of mockup height
  rotation        Decimal        @default(0)
  shape           String         // "RECTANGLE" | "ELLIPSE"
  minDpi          Int            @default(150)
  variant         ProductVariant @relation(fields: [variantId], references: [id], onDelete: Cascade)
}
All four positional fields (printAreaX, printAreaY, printAreaWidth, printAreaHeight) are expressed as percentages of the mockup image dimensions, not pixels. This ensures the template remains correct at any rendered size. A rotation value rotates the print area overlay clockwise in degrees; the default is 0. The shape field controls which clipping mask the editor applies — RECTANGLE for flat products like t-shirts and notebooks, ELLIPSE for round surfaces like mugs.

Minimal example

{
  "variantId": "var-3",
  "mockupImageUrl": "/mockups/taza.png",
  "printAreaX": 15,
  "printAreaY": 25,
  "printAreaWidth": 70,
  "printAreaHeight": 50,
  "rotation": 0,
  "shape": "ELLIPSE",
  "minDpi": 150
}
This template places a 70 × 50% elliptical print area starting at 15% from the left and 25% from the top of the mug mockup image.

How the Fabric.js editor uses the template

When a customer opens the design editor, the application fetches the full product via GET /api/catalog?id=<id> and reads the selected variant’s PrintTemplate. The editor mounts a Fabric.js canvas precisely over the element matched by either [id*='krafta-print-area'] or [id*='_x23_krafta-print-area'] in the SVG mockup. The dual selector handles SVG files that have been through an encoding pipeline that prefixes # characters as _x23_. The print area coordinates are converted from percentages to pixel positions at render time based on the displayed image size. The canvas accepts customer uploads (PNG, JPG, PDF, SVG), rasterises them if necessary, and clips the result to the shape defined by the template. Any object dragged outside the print area boundary is flagged with a visual warning; the submit button remains disabled until all design objects are within bounds and DPI requirements are met.

SVG variable system

Products that have an svgContent field use the Master Interactive SVG workflow. Within the SVG markup, any element whose id attribute contains the string krafta-var- (or the encoded form _x23_krafta-var-) is treated as an adjustable variable. The editor scans the loaded SVG for these elements using [id*='krafta-var-'] and [id*='_x23_krafta-var-'] and surfaces them as controls in the customization panel.
<!-- This circle fill is exposed as a customer-adjustable colour -->
<circle id="krafta-var-bodyColor" fill="#FFFFFF" ... />

<!-- This path fill is a second variable -->
<path id="krafta-var-sleeveColor" fill="#CCCCCC" ... />
When the customer changes a variable, the editor updates the corresponding element’s fill attribute in real time, and the live mockup preview reflects the change immediately without a round trip to the server.

File upload constraints

The editor enforces the following constraints on any file a customer attempts to upload:
ConstraintValue
Accepted formatsPNG, JPG, PDF, SVG
Maximum file size20 MB
SVG with scriptsRejected — files containing <script> tags are refused with a 400 error
Validation methodMagic-byte check for PNG/JPG/PDF; text-content inspection for SVG
Magic-byte validation runs server-side before the file is written to storage. PNG, JPG, and PDF files are validated against known binary signatures (the hex signature of the first bytes is stored in DesignUpload.magicBytes). SVG files are validated by inspecting the text content for <svg or <?xml at the start of the file; any SVG containing a <script> tag is rejected outright rather than sanitised.

DPI check

Before a design is accepted for production, the effective DPI of the artwork at the actual print size is calculated using the formula:
effectiveDpi = (sourceWidthPx / printedWidthInches) 
             = (sourceWidthPx / printAreaWidth) × targetDpi
In plain terms: the source image must supply at least minDpi pixels per printed inch. With the default minDpi of 150, a design intended to cover a 10-inch print width must be at least 1500 pixels wide. If the calculated effective DPI falls below minDpi, the editor displays a resolution warning and blocks submission.

SurfaceTemplateVersion — advanced versioned templates

For complex or frequently-revised products, Krafta supports a versioned template system through SurfaceTemplateVersion. This model decouples the template configuration from the product variant so that a new version can be drafted and tested before replacing the published one.
model SurfaceTemplateVersion {
  id           String        @id @default(uuid())
  templateKey  String        // e.g. "hoodie-crop-ls12000-printify-217-black-back"
  title        String
  subtitle     String?
  version      Int           @default(1)
  status       String        @default("DRAFT") // "DRAFT" | "PUBLISHED" | "ARCHIVED"
  manifestJson Json          // Full template configuration object
  createdAt    DateTime      @default(now())
  updatedAt    DateTime      @updatedAt
  mockupScenes MockupScene[]
}
The templateKey is a human-readable slug that identifies a logical template across versions. The manifestJson field holds the complete rendering configuration, including layer order, blending modes, and print area definitions. Only one version per templateKey should have status: "PUBLISHED" at any given time; the rest are either in DRAFT or ARCHIVED.

MockupScene — composite rendering modes

Each SurfaceTemplateVersion can have multiple MockupScene records that describe how to composite the customer’s design onto the mockup using different rendering techniques:
model MockupScene {
  id                       String                 @id @default(uuid())
  surfaceTemplateVersionId String
  mode                     String                 @default("flat") // "flat" | "cylinder" | "mesh"
  baseImageUrl             String
  productMaskUrl           String?
  shadowUrl                String?
  highlightUrl             String?
  displacementMapUrl       String?
  configJson               Json?
  surfaceTemplateVersion   SurfaceTemplateVersion @relation(fields: [surfaceTemplateVersionId], references: [id], onDelete: Cascade)
}
ModeDescription
flatSimple rectangular overlay; used for flat products like notebooks and posters
cylinderCylindrical warp; used for mugs and bottles using displacementMapUrl
meshFree-form mesh warp; used for apparel using displacement and highlight layers
The productMaskUrl isolates the printable surface from the background. shadowUrl and highlightUrl are blended on top of the customer’s design to add realistic depth and sheen.

Build docs developers (and LLMs) love