DEV Community

Mohamed Amine Ben Mallessa
Mohamed Amine Ben Mallessa

Posted on • Originally published at gist.github.com

From fragile iframes to server-side PDFs: a rendering migration story with Playwright

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)