By Mohamed Amine Ben Mallessa β Lead Dev at Sollea AI
The technical context
The application we shipped generates customized posters from a simple web form. Users fill in their event details (dates, venue, times) and the app produces a print-ready document.
Tech stack: Next.js 15 (App Router, TypeScript, TanStack Query) + FastAPI (SQLAlchemy 2, PostgreSQL). Modern stack β but document rendering was the weak link.
The trap of "free" solutions
When we started, Photopea looked ideal: a free Photoshop clone, scriptable via JavaScript. In production, it turned into a maintenance sink:
Issue #1: The elusive iframe
PSD files had to be publicly hosted with Access-Control-Allow-Origin: *. A CORS requirement that the client's infrastructure couldn't meet.
Issue #2: Ghost exports
Exports traveled through a backend API route (/photopea/exports). Network latency or timeouts could silently truncate exports.
Issue #3: No server-side rendering
Everything went through the client's browser. No automated generation, no CI/CD pipeline.
Issue #4: The black box effect
When a poster had rendering issues, nobody could tell if the problem was Photopea, the network, the PSD, or the code.
The fix in 3 decisions
Decision 1: HTML template = poster
Instead of a closed PSD, each poster format is an open HTML file versioned in the repo. Full control of layout, CSS, SVG.
Decision 2: Playwright for server-side render
Headless Chromium via Playwright produces a perfect vector PDF and high-res PNG. Average time: 3.5 seconds per poster. Fully reproducible.
Decision 3: Single source of truth
The same HTML template serves both the live iframe preview AND the Playwright final render. Zero difference between preview and printed document.
The numbers
| Metric | Before (Photopea) | After (HTML Engine) |
|---|---|---|
| External dependencies | 2 (Canva, Photopea) | 1 (Playwright) |
| License cost | $$$$ (Canva Enterprise) | $0 |
| Render time | 30-60s (network dependent) | ~3.5s |
| Server-side render | Impossible | PDF + PNG |
| Reliability | Fragile | Robust |
| Adding a template | Complex config | One folder + manifest |
What I learned
"Free" solutions with complex infrastructure often end up costing more than a simple solution you fully control.
An HTML template isn't as powerful as a PSD β but it has three decisive advantages: it's readable, versionable, and reproducible.
Thanks to Nassim Tarkhani for pushing this direction. This idea saved the project.
Mohamed Amine Ben Mallessa β Lead Dev at Sollea AI
π GitHub | LinkedIn
Need help with your technical stack? Sollea AI specializes in custom automation and AI solutions.
playwright #html #pdfgeneration #fastapi #nextjs #engineering #webdev #architecture
π» Have a similar project?
Sollea AI β Full-stack development, AI automation, custom solutions.
π Sollea AI Β· GitHub Β· LinkedIn
Team led by **Mohamed Amine Ben Mallessa* β Lead Dev at Sollea AI*
Top comments (0)