Engineering for Efficiency: Building a Custom Product Configurator to Automate Logistics
Context: In the world of personalized e-commerce on marketplaces like Allegro, the biggest bottleneck isn’t manufacturing—it’s matching the user’s design to the specific transaction without errors. Here is how I solved this problem with code.
The Problem: “Which ‘Anna’ ordered this mug?”
Selling custom products on Allegro (Poland’s largest marketplace) comes with a specific disconnect: the design tool lives outside the marketplace.
Most competitors solve this lazily: after designing a mug, they ask the user to “Type your Allegro Nickname” in a form. This is bad design.
- Typos: Users frequently make typos, especially with auto-generated Allegro logins (e.g.,
Client:12345678), which are hard to remember and type correctly. - Identity Mismatch: Users often provide their Real Name (e.g., “Anna Nowak”) instead of their Allegro Login. Since multiple customers can have the same First/Last name, it becomes impossible to match the design to the correct order without a unique identifier.
- Ambiguity: What if one user places three separate orders for three different designs?
This manual matching process was error-prone and slow. I needed a deterministic way to link an anonymous external design to a specific Allegro transaction, while also solving the issue of users sending low-resolution photos via email.
The Solution: iCUP.pl
I built a custom Single Page Application (SPA) that acts as a bridge between the user’s creativity and my logistics system.
The Stack
- Frontend: Vanilla JavaScript + Fabric.js (Handles all logic, rendering, and export).
- Backend: Native PHP (Handles upload receiving, ID generation, and storage).
- Image Processing: ImageMagick (Generates 3D previews from the uploaded flat design).

The Technical Challenges
1. The Custom Cropping Engine (Coordinate Geometry)
The engineering heart of this project is the manipulation logic. Users upload images in every conceivable aspect ratio, but they must fit perfectly into fixed “Template Slots” or user-defined crop areas.
Since I couldn’t rely on basic CSS masking for the final export, I had to build custom logic on top of Fabric.js. The interaction model is specific: The image is locked in place, and the user manipulates a “Crop Frame” over it.
To enhance the user experience, I implemented a “Focus Mode” for cropping: when a user enters crop mode, the target image is temporarily enlarged to fill the entire canvas area. This maximizes the working space and precision on small screens. The algorithm tracks this temporary scale change and ensures that when the user confirms the crop and the image returns to its original size, the crop coordinates are correctly translated.
Designing a mug in a minuteThe Math Problem: The challenge is translating the coordinates of the moving Crop Frame (which exists in the global Canvas coordinate system) into the local coordinate system of the Underlying Image (which has its own scale and dimensions, distinct from the temporary view scale).
I implemented an algorithm to calculate this projection manually. Here is a snippet of the logic used to calculate the relative offsets:
function cropImageRect() {
// ... (setup: retrieve cropFrame and croppingObjectCentered objects)
// 1. Calculate cropped dimensions based on intersection
// Crucially, divide by current scale (scaleX/scaleY) to get intrinsic pixel values
var width = (cropFrame.aCoords.br.x - cropFrame.aCoords.tl.x) / croppingObjectCentered.scaleX;
var height = (cropFrame.aCoords.br.y - cropFrame.aCoords.tl.y) / croppingObjectCentered.scaleY;
// 2. Calculate new origin point (Top/Left) relative to image's internal coordinates
var newLeft = (cropFrame.aCoords.tl.x - croppingObjectCentered.aCoords.tl.x) / croppingObjectCentered.scaleX;
var newTop = (cropFrame.aCoords.tl.y - croppingObjectCentered.aCoords.tl.y) / croppingObjectCentered.scaleY;
// 3. Apply calculated dimensions to Fabric.js object state
// Updates the "view" of the image without destroying original data
croppingObjectCentered.cropX = newLeft;
croppingObjectCentered.cropY = newTop;
croppingObjectCentered.width = width;
croppingObjectCentered.height = height;
canvas.renderAll();
// ... (cleanup: reset UI state, hide crop controls)
}
This manual calculation ensures that the “cut” is mathematically precise, regardless of the image’s scale or aspect ratio.
2. Strict Z-Index Management (The Layering Engine)
A standard canvas allows free movement of objects, but a product configurator requires strict hierarchy.
- Background Layer: (Fixed bottom)
- Image Frames: (Where users drop photos)
- User Content: (The photos themselves)
- Foreground/Overlay: (e.g., text or graphical overlays that must stay on top)

Fabric.js tends to bring the selected object to the front. To prevent a user’s photo from accidentally covering the “Mug Overlay” or “Text Template,” I implemented a layer enforcement function (fixProjectLayers) that runs after object modifications to re-sort the canvas stack.
function fixProjectLayers() {
var canvasObjects = canvas.getObjects();
// Iterate backwards to push specific groups to the bottom in order
for (i = (canvasObjects.length - 1); i >= 0; i--) {
if ((canvasObjects[i].id || "").includes("projectText_")) {
canvasObjects[i].sendToBack();
}
}
// Ensure Image Frames stay behind text but above background
for (i = (canvasObjects.length - 1); i >= 0; i--) {
if ((canvasObjects[i].id || "").includes("imgFrame_")) {
canvasObjects[i].sendToBack();
}
}
// Force Background to the absolute bottom
if (canvas.getObjects().find(obj => obj.id === "bg")) {
canvas.getObjects().find(obj => obj.id === "bg").sendToBack();
}
canvas.renderAll();
}
This ensures the visual structure remains broken-proof, even when users interact aggressively with the elements.
3. Client-Side Rendering for True WYSIWYG
A common pitfall in web-to-print systems is the discrepancy between what the user sees in the browser (HTML/CSS/Canvas) and what the server renders later.
To guarantee 100% fidelity, I shifted the entire rendering responsibility to the client side.
- The Process: The browser uses Fabric.js to handle complex layering, masking, and text rendering.
- The Export: When the user saves the project, the client generates the final, high-resolution print file directly from the Canvas (using
toDataURLwith a resolution multiplier). - The Result: The backend receives a finished
.pngfile that is a pixel-perfect representation of the user’s design. This eliminates the complexity of trying to reconstruct frontend state on the backend.
4. Mobile-First Interaction (Zoom Controls)
Over 70% of my traffic is mobile. Standard “pinch-to-zoom” gestures often conflict with browser navigation, and even enlarged corner handles proved frustrating on small screens.
To solve this, I added dedicated “Zoom In / Zoom Out” buttons to the UI. This simple addition allows users to scale photos with precise taps instead of finicky drag gestures, significantly speeding up the design process on mobile devices.
The Integration: Regex & The “Project ID” Protocol
The smartest part of this system isn’t the graphics editor—it’s how it talks to my ERP, Monmat Manager.
Since I cannot inject data directly into Allegro’s database, I created a Unique Project ID protocol.
- Generation: When a user saves a design, the system generates a unique hash.
- Instruction: The user is instructed to copy this ID and paste it into the “Message to Seller” field on Allegro.
- Automation:
- Scenario A (Perfect Flow): The user pastes the ID in the order message. My ERP fetches the order via Allegro API, detects the ID using Regex, and automatically downloads and links the print files to the order.
- Scenario B (Chat Flow): The user forgets and sends the ID in a private message later. I simply copy the message content into the “Notes” field in my ERP. The same Regex logic triggers, parsing the note and linking the project instantly.
The Business Impact
- Operational Scalability: The system decouples sales volume from administrative workload. I no longer spend hours daily explaining file requirements to customers via email.
- Mobile Conversion: Providing a native-like experience (with zoom buttons and optimized touch handles) on mobile devices significantly reduced cart abandonment compared to competitors’ desktop-centric tools.
- Logistics Speed: The automated pipeline allows for same-day shipping even for personalized orders placed as late as 3 PM, as the print file is ready the moment the order is imported.
Conclusion
Building iCUP.pl taught me that “Full Stack” isn’t just about code—it’s about understanding the platform constraints (Allegro) and engineering a workflow that bypasses them. By replacing manual matching with Regex automation, I turned a logistical nightmare into a competitive advantage.