Should I vibe code
Publish a portfolio and client galleries with basic downloads
A gallery that sells prints is a shop with a factory attached. The bad crop ships, and it ships to her mother.
?
Their verdict, the Professional price and the build-time estimate come from their entry, MIT-licensed. Checked 2026-08-04.
?
Our verdict, the regret score and everything below it. Editorial and unsponsored — nobody can pay to be moved.
The honest answer
why the verdict is what it is
The Pixieset entry covers the gate and the Pic-Time entry covers the decade; this is the third failure in the same product shape, and it is the one that ships in a box. Zenfolio's paid tier exists to sell prints — a guest picks an image, picks a size, pays, and a professional lab somewhere prints and ships a physical object to an address they typed into your form. That sentence is a storefront with a factory bolted to it, and every part of it is unlike the gallery you built to get here. Prices have to map onto a lab's product catalogue and stay above its costs. Sales tax on a physical good is decided by where the buyer lives. The file you send needs the lab's colour profile, not your monitor's. And a 3:2 photograph ordered as an 8x10 has to lose an inch and a half of something, so the crop is a decision your code will make silently, forty times, in a single family's order. None of it is unbuildable; all of it is un-undoable. A leaked link can at least be revoked. A print is in an envelope, with somebody's chin missing, addressed to the grandmother.
What actually breaks
not "if". the specific failures.
- Aspect-ratio cropping, which is the defining bug of every homemade print store: a 3:2 frame sold as an 8x10 loses an inch somewhere, and your code picks where
- Colour, when files go to the lab in your working profile rather than theirs and the skin tones come back a different person
- The order handoff, where a payment succeeds and the lab submission fails, so the money is taken and nothing is printed until somebody emails to ask
- Price mapping, once the lab's cost list changes and your published price is now below what the product costs to make
- Sales tax on physical goods, which depends on where the buyer is rather than where you are
- Shipping addresses, which are personal data belonging to people who never met you — often dozens of them per wedding
- Refunds for an object that already exists, since the print cannot be un-made and the lab has already been paid
- Chargebacks, weeks later, on an order you cannot reconstruct because the cart lived in a session
- Storage costs, which accumulate against a shoot fee you were paid once, years ago
The email is forwarded by the bride, and it is her mother's, which somehow makes it worse. She ordered eleven 8x10s from the gallery for the family — one for each set of grandparents, one for the aunt who could not travel — and they have arrived, and in every one the top of somebody's head is gone. You know instantly what happened, because you remember writing it: the originals are 3:2, the frames are 4:5, and the resizer center-crops. It looked fine on a landscape of the venue. It looked fine on the two portraits you tested. It does not look fine on a formal group shot where the tallest person is at the edge, and it definitely does not look fine eleven times in a row, printed, matte, in envelopes that went out on Tuesday. The lab did exactly what it was asked. The money has been taken, the prints exist, and there is no version of the fix that involves a deploy. It is a reprint order you pay for yourself, an apology to a client who was recommending you to her friends, and the realisation that a preview thumbnail was the only place that crop was ever visible before the paper.
Is that you?
the verdict is a default, not a law
- It is a portfolio and nothing else — your own photographs, no client galleries, no store
- Prints are ordered by you, by hand, from your lab's own site, with the gallery only collecting a wish list
- Every image byte is served through short-lived signed URLs from the gate, with no public object path anywhere
- Payment, if any, is hosted Stripe Checkout and no card detail reaches your server
- You self-host Lychee or Immich for the gallery and keep the commerce somewhere that already knows about tax and shipping
- You are selling physical products to a client's guests and have not decided who eats a bad print
- The crop for each product size is chosen by your code rather than confirmed by a human against a preview of the actual print area
- Sales tax is a constant in your checkout and your buyers are in more than one state or country
- Orders reach the lab by an integration with no retry, no alert and no way to see what is stuck
- You are hosting other photographers' stores, which makes their refunds and their tax your operational problem
If you build it anyway
the checklist, then the prompt that enforces it
- Show the actual print area before the sale. A live crop preview per product size, chosen or confirmed by a human, is the single control that prevents the most expensive failure in this entire product.
- Send the lab exactly what the lab asks for: their colour profile, their resolution floor, their bleed. Build a hard check that refuses to submit a file that fails those constraints rather than letting it through.
- Treat the lab submission as an outbox with retries, statuses and an alert. A paid order that never reached the lab is invisible until a customer chases it, and by then it is late.
- Never take card details yourself. Hosted Stripe Checkout keeps card data off your infrastructure and out of the standard.
- Reconcile against the payment provider nightly and alert on any order whose payment state and fulfilment state disagree.
- Decide the sales tax question before you publish a price — destination-based rates and marketplace rules are not something to discover from a customer.
- Store shipping addresses as sensitive personal data with a retention period, and build the deletion path in the same afternoon you build the checkout.
- Set a floor on prices derived from the lab's live cost list, and alert when a published price drops below cost plus your margin.
- Keep the gallery access model from the Pixieset entry regardless: signed URLs, random tokens, no public bucket path. A store on top of a leaky gallery is two problems.
I am building client photo galleries that sell physical prints through a print
lab. The output is a physical object mailed to a stranger, so treat every
irreversible step as the priority and refuse the shortcuts that make a grid feel
fast.
1. Build the crop UI before the store. For every product size, show the exact
print area over the image and require a human to confirm it. Never centre-crop
silently to fit an aspect ratio, and tell me why when I ask you to.
2. Encode the lab's requirements as validation: colour profile, minimum pixel
dimensions, bleed. An order that fails validation is rejected at the point of
sale, not at the lab.
3. Model fulfilment as an outbox — order rows with status, attempts and last
error, a worker with backoff, and an alert on permanent failure. A paid order
that never reached the lab must page me, not sit in a log.
4. Payment is hosted Stripe Checkout only. No card form. Write the nightly
reconciliation between payment state and fulfilment state before the
storefront exists.
5. Ask me where my buyers are and refuse to hardcode a sales tax rate. Say
plainly that tax on a shipped physical good follows the buyer's address.
6. Derive every published price from the lab's current cost list plus my margin,
and alert me when a price would sell below cost.
7. Shipping addresses and buyer emails are personal data belonging to people who
never hired me. Give them a retention period and a working deletion path in
the same change that collects them.
8. Refunds are money movement and the object still exists. Make them idempotent,
logged with an actor, and require a reason code so I can see which product
sizes keep going wrong.
9. Keep the gallery access model strict: every image byte through short-lived
signed URLs after the gate, gallery ids as long random tokens, no public
object paths, listing disabled.
10. Strip EXIF from anything downloadable, and remind me that GPS in a home
session points at where the client lives.
11. Out of scope unless I ask again: albums, wall-art configurators, gift cards
and self-fulfilment inventory.
12. Finish by telling me what Zenfolio costs a month and what a single reprint
run costs me, and let me compare the two numbers.That one keeps you out of trouble. For the prompt that actually builds it, canivibecodeit.com has one.
their build prompt ↗Or don’t build it
the boring option, and the way back out
The moment a stranger can hand you money for a physical object. Twenty-three dollars a month is less than one reprint run plus the postage, and what it buys is a print pipeline — labs, colour profiles, crop previews, tax, shipping, refunds — that has been corrected by other people's ruined orders for over a decade. Build the portfolio yourself if you like; it is a genuinely nice weekend. Let somebody else own the part that ends up in an envelope.
$23/mo is cheaper than your weekend.
Keep the photographs in a bucket you control, foldered by client and date so a human can navigate them without your database, and keep the commerce in systems that outlive the app: charges in Stripe with the order id in metadata, fulfilment records exported from the lab's own dashboard. What exists nowhere else is the order history — who bought which image at which size, and the crop that was approved — so export that as JSON on a schedule, because it is what a reprint request two years from now is answered from. When you switch the app off, confirm that every previously public gallery URL returns 403 and that no pending order is stranded between paid and printed.
Self-hosted photo management with password-protected albums and share links, which covers the gallery half without the store.
Active open-source self-hosted photo and video management platform.
Questions
Three photographer entries, three YOUR FUNERALs. What is different here?
The failure leaves the computer. Pixieset's entry is about a private gallery that stops being private in week one, and Pic-Time's is about the ten-year delivery promise you accidentally made. Zenfolio's paid tier sells prints, so its characteristic failure is an object that has been manufactured, paid for and posted before anybody sees the mistake. A leaked link can be revoked and a dead gallery can be rehosted. A box of badly cropped 8x10s is a reprint order and an apology.
Is the crop really the biggest risk?
It is the one that gets people, because it is invisible in the medium you are testing in. On screen every image is whatever aspect ratio you serve it at; on paper the sizes are fixed and something has to give. Automatic centre-cropping looks fine on landscapes and on the two portraits you tried, and then a formal group shot gets sold at 8x10 eleven times. Show the print area, make a human confirm it, and most of this entry stops applying.
Can I keep the gallery and skip the store?
Yes, and it is the honest recommendation. A portfolio plus delivery galleries is a good build with a known risk profile — read the Pixieset guardrails, serve every byte through signed URLs, and you have most of the product. Selling prints is where you take on payments, tax, fulfilment and a manufacturing partner, which is not an extra feature so much as a second business.
What about the storage bill?
It is real and the Pic-Time entry covers it properly. Zenfolio's tiers ladder from 15GB to unlimited JPEG for a reason: photographers accumulate, clients come back years later, and you were paid once. If you host it yourself, the bill grows every month against revenue that already happened, and the decision to delete an old wedding gallery is one nobody ever wants to be the person making.
- PCI DSS standards library
- Stripe — reducing your PCI scope
- GDPR Art. 5 — principles relating to processing of personal data (EU)
Every week, someone ships something they shouldn’t have.
New verdicts, the worst thing that landed in the trap, and the occasional incident report. No other email, ever.
The password gates the page. The JPEGs sit on a public bucket path, and Google does not need the password.
You are not delivering photographs. You are promising a URL still resolves on their tenth anniversary.
Your portfolio is built to be crawled. The gallery beside it holds a campaign that has not launched yet.
last reviewed 2026-08-05 · verdict is editorial and unsponsored · shared entry data from canivibecodeit under MIT · not legal advice