Repository navigation
Studio: import slide decks (.pptx/.ppt/.odp) as PDF via a LibreOffice container - #98
Merged
Merged
Conversation
leorfer23
force-pushed
the
feat/pptx-to-pdf
branch
3 times, most recently
from
October 14, 2026 19:42
6ba37d2 to
4fd66ce
Compare
… container - New optional SLIDES_CONVERTER binding: a Cloudflare Container (Debian trixie + LibreOffice Impress, containers/slides/) behind the SlidesConverter Durable Object (@cloudflare/containers 0.3.7, no outbound internet, sleeps after 2m). No public route reaches it; only POST /v1/home/import calls it. - Import: a deck becomes a private pdf artifact; the original is kept at original/<file> and recorded in type_metadata.source, like Word/Excel (#93). - Guards: 25 MB import cap (413 FILE_TOO_LARGE, also enforced in the container), 90 s worker / 75 s LibreOffice timeout (422 CONVERT_TIMEOUT), busy container 503 CONVERT_BUSY, bad output 422 CONVERT_FAILED. Nothing is published on any failure. - Without the binding: the client keeps routing decks to Recursos (no behavior change; gated by window.WSX_SLIDES), and the API answers 422 CONVERT_UNAVAILABLE. Copy in en/es. - Studio inspector: "Download original" for pdf artifacts that kept one (GET /v1/artifacts/:id now returns `original`). - wrangler.toml: commented [[containers]] + binding + migration v9 block; deploy doc lists the optional binding. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
leorfer23
force-pushed
the
feat/pptx-to-pdf
branch
from
October 14, 2026 19:48
4fd66ce to
8b0dca7
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
A customer drops a
.pptx(or.ppt/.odp) on the Studio Home and gets a private pdf artifact (viewer from #88). The original deck is kept atoriginal/<file>, recorded intype_metadata.source, and downloadable, the same way #93 handles docx/xlsx.Conversion runs in LibreOffice inside a Cloudflare Container, behind an optional
SLIDES_CONVERTERDurable Object binding.How
shareout-app/containers/slides/:Dockerfile(pinneddebian:trixie-20260918-slim,libreoffice-impress, metric-compatible fonts Carlito/Caladea/Liberation) andserver.py(stdlib HTTP on :8080,POST /convert, non-root user, per-request LibreOffice profile, at most 2 conversions at once, kills the process group after 75 s).src/pages/home/slides-converter-do.ts:SlidesConverter extends Container(@cloudflare/containerspinned0.3.7),enableInternet = false,sleepAfter = '2m'. It's exported fromsrc/index.ts. Nothing routes public traffic to it. Onlyimport-slides.tscalls it through the binding.src/pages/home/import-slides.ts: calls the converter (90 s worker timeout), checks the output is really a PDF, and returns{ pdf, original }+source.import.ts/import-rules.ts:IMPORT_SLIDES_EXTS→ artifact typepdf. Decks must be sent base64, with the same 25 MB cap as the other imports.drop-import.ts): decks go to import only whenwindow.WSX_SLIDESis set (!!env.SLIDES_CONVERTER). Otherwise they still go to Recursos, so instances without the binding behave exactly as before.GET /v1/artifacts/:idnow returnsoriginalwhen the artifact kept one.Errors (nothing is published, rate limit not consumed)
CONVERT_UNAVAILABLE(en/es copy: "export it as PDF")FILE_TOO_LARGECONVERT_TIMEOUTCONVERT_BUSYCONVERT_FAILEDImport-rules note (#93)
#93 merged before this PR, so this PR includes the
.pptxroute itself. No follow-up needed.IMPORT_ARTIFACT_EXTSis unchanged (decks aren't unconditionally artifacts). The binding gates them viaIMPORT_SLIDES_EXTS+WSX_SLIDES.Checks (local, no Actions)
tsc --noEmitcleannpm run test:affected: all green after fixes (new tests inhome-import.test.ts,home-drop-import.dom.test.ts,get-artifact.test.ts)ci-check-fast.sh) passed on push, no--no-verifylinux/amd64) and converted a real 2-slide.pptx→ 2-page PDF with text intact ("Revisión Q3…"). Chunked bodies → 200, bad ext → 415, junk bytes → 422, 27 MB → 413. Temp dirs are cleaned up and the process runs as uid 10001.wrangler deploy --dry-runwith the container blocks uncommented: config valid,env.SLIDES_CONVERTERbound, containershareout-slidesconverterdetected. A dry-run of the stock config also passes.Prod deploy needs (not done here; no prod config touched)
shareout-private/wrangler.prod.toml) the three blocks commented inshareout-app/wrangler.toml:[[containers]](class_name = "SlidesConverter",image = "./containers/slides/Dockerfile",instance_type = "standard-1",max_instances = 1), theSLIDES_CONVERTERDO binding, and anew_sqlite_classes = ["SlidesConverter"]migration with the next free tag in prod's migration list (the OSS template usesv9).wrangler deployruns, because it builds and pushes the image to the Cloudflare registry (compressed image is about 190 MB). The first deploy provisions the container, and it can take a few minutes before conversions answer instead ofCONVERT_BUSY.Cost notes (from the pricing page, 2026-10): billed only while awake, and it sleeps 2 min after the last conversion.
standard-1= ½ vCPU / 4 GiB. A cold conversion keeps it up about 2–3 min, roughly $0.003 above the included usage. Included monthly: 25 GiB-h memory (≈6 h awake at 4 GiB) and 375 vCPU-min.max_instances = 1bounds spend, and concurrent imports beyond 2 queue or getCONVERT_BUSY. Raisemax_instancesand spread names if volume grows.Not verified
startAndWaitForPortsagainst this image, and the DO→container request path. Tested only with a localdocker runand stubbed binding unit tests.wrangler devwith the container (local container dev)..ppt/.odpreal-file conversion (only.pptxconverted for real; the other two share the code path).🤖 Generated with Claude Code