OKPrint
A live photo-printing e-commerce platform (okprint.ma) combining product ordering, photo uploads, media management and a local print-fulfillment agent, plus a separate live photo-booth variant for events.
Role
Full-stack developer — storefront, admin, image pipeline and deployment
Context
OKPrint is a live photo-printing e-commerce platform at okprint.ma, where customers choose a print product, upload their own photos, and order prints — alongside a separate photo-booth variant of the same platform built for live photo capture at events.
System
A Node.js/Express API (Sequelize over MySQL) serves the storefront and admin: product/category management, multi-store support, and printer configuration. Customers upload photos through multipart form data (with a base64 fallback), which are processed — cropped, resized, prepared for print — and attached to an order moving through cart and checkout. A separate Python/Flask agent runs on a shop's local network, pulling finished images from the API and sending them to the physical printer over the native Windows print API. The app deploys to a DigitalOcean droplet through a GitHub Actions pipeline that restarts the service under PM2.
Problem
Customers need a straightforward path from choosing a product to seeing their own photo printed, while the shop side needs to manage multiple stores and printers, review and clean up uploaded images, and keep the whole pipeline — upload, processing, cart, checkout, print — working reliably in production.
Engineering challenge
Handling two different upload paths (multipart and base64) into the same processing pipeline, keeping uploaded and processed images manageable for admins to review and delete, supporting more than one store/printer configuration from the same backend, and getting a physical printer on a shop's local network to reliably receive and print jobs dispatched from a cloud-hosted API.
My contribution
- Built the storefront workflow (product/category selection, photo upload, cart, checkout) and the admin side (product, store and printer management, image review and cleanup).
- Implemented multipart and base64 photo-upload paths into a shared image-processing pipeline.
- Built and maintain the Python/Flask local print agent that bridges the cloud API to a physical printer over the shop's local network.
- Set up and maintained the GitHub Actions → DigitalOcean → PM2 deployment pipeline, and debugged production issues on the live site.
Technical decisions
- Kept a base64 upload path alongside multipart form-data, since not every client context could reliably send a multipart request.
- Split the event/photo-booth product (live camera capture and event-only features) into its own front end and backend variant rather than overloading the main storefront.
- Ran the print agent as a separate local application rather than trying to reach a shop's printer directly from the cloud API, since a LAN-local agent is the only reliable way to reach store hardware.
Technology
- React / Redux Toolkit
- The customer storefront (product/category selection, upload, cart, checkout) and the admin dashboard.
- Node.js / Express
- The storefront and admin API.
- Sequelize / MySQL
- Product, order, multi-store and image records.
- Multer (multipart/form-data)
- Handles photo uploads, alongside a base64 upload path for clients that need it.
- Sharp / canvas
- Crops, resizes and prepares uploaded photos for print.
- JWT
- Role-scoped authentication for admin and store users.
- Python/Flask print agent
- A LAN-local companion app that sends finished images to the shop's physical printer over the Windows print API.
- GitHub Actions + PM2
- SSH-based deploy pipeline to a DigitalOcean droplet.
Result
A live, in-production e-commerce platform with a working upload-to-print pipeline, a separate event-product variant, and its own local-network print agent — deployed and operated on DigitalOcean.
What I learned
The hardest part of a project like this usually isn't the storefront — it's the seam between the cloud API and a physical device on someone else's network, and between two different ways clients send you the same kind of data.
Deployed to DigitalOcean via GitHub Actions → PM2