Commits
Multi-edition ready: closed tickets, three user bugs, and a printing decision
A morning of tickets (03-06), with the end-to-end run green and three user reports uncovering invisibility bugs, a colophon with no height, and a decision: client PDFs are painted over the template, never used to replace it.
Saturday morning and a full day dedicated to closing out the multi-edition functionality. The session carried over from the night of the 26th, and the plan was clear: finish the outstanding tickets and leave everything ready for validation with real-world material. By the end, it wasn't just about closing tickets: the day turned toward three user reports that uncovered more subtle problems than those in the new code.
The morning went quickly. Ticket 03 was resolved with a single "fixed + custom fields" mechanism shared by the magazine identity and the issue sheet: the renderer no longer reads tema.yaml and numero.yaml, and the template context is now revista.* and numero.*, with the template deciding what to render, as we had agreed. Ticket 04 brought the renderer's biggest new feature: each side of the magazine accepts either a background image or a closed PDF that replaces the generated page. The technical risk—painting the background with WeasyPrint beneath the content—worked on the first try, verified with a real PDF. Ticket 05 turned the trash into a Cleanup section with manifests: each deletion stores its source, date, and content, and can be restored with one click.
The day's most satisfying result was ticket 06, the end-to-end test of the entire feature against a clean instance. Issue n87 was created with the ISSN as a custom field rendered on the cover, a PNG background, and a closing announcement with bleed; the two articles were uploaded, extracted, reordered, and laid out; the export produced all eight checks in green and "Ready for print." Along the way, two honest lessons emerged: the first export came out red because my test material was not fit for purpose—a photo at 181 ppi and an announcement without bleed—and the preflight was doing exactly its job. And qpdf wasn't installed on the laptop, with its warning dragging down the overall verdict; installed via Homebrew, the same approach used for Ghostscript.
At noon, the three user reports arrived, bringing with them the day's most important lesson. The first: the cover image was not visible. There were two overlapping bugs—WeasyPrint caches images by URL, and the background was always named <lado>.png, so the second uploaded background never made it into the PDF—and the decisive one: the background was included as an <img> with z-index -1, which paints BEHIND the container's background, and the cover's dark color covered it. The image was in the PDF but invisible. The second report: the colophon appeared at the top and was cropped. Absolute positioning at the bottom was resolving against the article box, and the colophon article had no height—bottom: 3mm on a zero-height box leaves the text hanging at the top. Solution: height: 255mm, the usable area of A4 with the template margins.
The underlying lesson is verification: my ticket 04 checks counted image XObjects on page 1—the image was REFERENCED there, but not VISIBLE. Now the tests rasterize with pdftoppm and count pixels of the expected color: actually visible or nothing. Three layers so as not to confuse "it is in the stream" with "it can be seen" again: extract, pixels, and eyes.
The third report culminated in an architecture decision. The user spotted via a screenshot that the client's PDF back cover looked larger than the rest: its MediaBox traveled intact into the final document, and the page ended up with a different physical size—a real printing risk. Following their proposal, the decision was: instead of replacing the page, the client PDF is painted over the template page using pikepdf's add_overlay, scaled cover-style and using the client's TrimBox as the origin if it has one. Result: all pages share the MediaBox, TrimBox, bleed, and the software's crop marks—a single MediaBox across the entire PDF, verified. And because the overlay covered the crop marks, they are redrawn on top as a Form XObject generated on the fly, only on closed pages.
The day wrapped up with two print adjustments informed by print-shop judgment. Closed materials now respect their position in the list—the renderer reserves an invisible placeholder page marked with transparent text and then paints the client onto it with bleed—and the multiple of 4 is calculated with the placeholders already included. The export gains two options: "Pure black text (K plate only)," which defines the ink as device-cmyk(0,0,0,1) and survives Ghostscript conversion intact, and the downsampling of images above the configured minimum resolution (300 ppi by default) during conversion. Final revalidation with everything assembled returned an all-green report. The feature is ready to validate with the user and perform the merge.