以 React、Cloudflare 和 Stripe 打造 Paper Adventure 可列印遊戲應用程式
Building Paper Adventure: a printable game app with React, Cloudflare, and Stripe
Paper Adventure Workshop 的開發案例記錄瞭如何以 React、Cloudflare 和 Stripe 建構面向家庭及課堂的可列印故事冒險應用程式。
I'm building Paper Adventure Workshop, a web app for printable story adventures for families and classrooms. An adult downloads the game, prepares the paper materials, and guides children through five connected checkpoints.
There are two product paths: ready-made games with existing files, and AI-assisted custom adventures built around a buyer's idea. Both need a Player Pack and a separate Host or Teacher Guide, with A4 and US Letter options.
This case study documents the engineering decisions behind turning generated content into a downloadable product.
The stack
- React and Vite for the interface, with pre-rendered public pages.
- Cloudflare Workers for the API and site delivery.
- D1 for orders, saved generation progress, entitlements, and support records.
- Private R2 storage for purchased files and generated covers.
- Cloudflare Queues for background generation work.
- Stripe Checkout and webhooks for payments.
The public catalogue and the private purchase flow have different jobs. Visitors should be able to explore a story before signing in. Purchased files need server-side ownership and access checks.
1. Treat payment and delivery as separate states
A successful redirect from a checkout page is not enough to unlock a file. The backend needs to confirm the payment and associate it with the correct order.
After that, a ready-made game and a custom game take different paths:
Ready-made:
confirmed payment -> entitlement -> existing downloadable files
Custom:
confirmed payment -> saved plan -> adult approval
-> background generation -> checked PDFs -> downloads
That distinction also matters in the interface. "Payment confirmed," "Generating," and "Files ready" should not be interchangeable labels. If generation stops, the paid order needs to stay visible with an explanation and a support path.
2. Save progress before moving to the next generation step
A single long-running request is an awkward place to build a complete game. If the final step fails, restarting everything can repeat work and spend more provider credit.
The custom flow saves progress between generation steps. Background jobs resume from saved work, and retries have bounded budgets. A queue message advances a generation step instead of asking the browser to wait for the whole process.
One particularly useful boundary is between checked game content and PDF rendering. A rendering failure should be able to reuse saved content rather than request another story.
The principle applies beyond games: save expensive, validated intermediate results before starting the next fallible operation.
3. A generated story still needs a game contract
A printable adventure needs more than an interesting premise. Players need materials they can handle, instructions they can follow, and clues that support an answer.
The implementation uses structured game data, deterministic puzzle checks, and paired PDF checks around the generated narrative. The player materials and adult answers have to agree. A story sentence should not imply that a clue exists when it was never printed.
This also affects product design. Home and Classroom editions have distinct stories and adult guidance, rather than being the same PDF with a different label.
Automated checks help catch contradictions and layout problems. Testing a printed game with real people is a separate part of evaluating its play quality.
4. Keep optional cover generation separate from the purchased files
The game cover and the game PDFs are separate outputs. A failed cover request should not remove access to a completed game.
This separation became especially concrete during development: failed historical cover requests left some library cards without illustrations even though their PDFs were available. Fixing a provider integration does not automatically repair every old record.
The lesson was to keep optional asset status explicit and handle historical recovery deliberately. Repeated refreshes should not keep submitting new paid image requests.
5. Design the download and support experience together
Once files are ready, the page should make the next action obvious:
- A complete ZIP as the main download.
- One paper-size selection for the matching files.
- Separate Player Pack and adult-guide downloads.
- A compact receipt and clear online access expiry.
- Order-linked help without asking the buyer to retype an order reference.
Support is part of delivery. Recording a request, notifying the operator, reviewing a refund request, and actually completing a refund are different events. The interface should describe the event that has happened.
What I'd like feedback on
For developers who have shipped generated documents or other asynchronous digital products: where do you draw the boundary between automatic recovery and an explicit user action? I'd also welcome feedback on making a print-first product understandable in a web interface.
Disclosure: Paper Adventure is my project. An AI agent prepared this article from the project's implementation and development notes at my request.
來源:DEV Community · dev.to