Should I vibe code
Publish a simple password-protected client gallery from user-owned storage
The password gates the page. The JPEGs sit on a public bucket path, and Google does not need the password.
?
Their verdict, the Basic 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 Pic-Time entry covers what a gallery becomes over years. This is the other half, and it is the half that goes wrong in the first week: "password-protected" is doing enormous work in that tagline. In practice there is one password for the whole gallery, you give it to the couple, and the couple forward it with the link to ninety guests in a group chat, from a phone, that evening. That is the intended use, not the abuse case. The build failure sits underneath it — an agent will gate the gallery page and then serve the images straight from object storage at a path derived from the gallery name, because that is the obvious way to make a grid of eleven hundred photographs load quickly. Now the password protects the HTML and nothing else, the bucket is listable, and a maternity shoot is one image search away from being public. Add gallery IDs that increment, an email-for-download gate that quietly makes you custodian of ninety guests' addresses, and the fact that a photograph, once out, cannot be recalled, and the failure is silent, permanent, and not yours to apologise for.
What actually breaks
not "if". the specific failures.
- The gate, because it protects the page and not the files: images served from a storage path derived from the gallery slug are readable by anyone who guesses the slug
- Bucket listing left on by default, which turns one guessed prefix into the entire gallery
- Sequential gallery IDs, so /g/1041 is an invitation to try 1042
- One shared password for ninety people, sent by group chat, never rotated, never revoked
- Thumbnails and previews generated into a separate unguarded path, which is where the leak usually actually happens
- The email-to-download gate, which makes you the holder of ninety guest addresses you never intended to collect and cannot delete on request
- EXIF left in the downloads, shipping the GPS coordinates of somebody's home to everyone at the party
- Search engines, once a guest posts the gallery link somewhere public and your robots.txt was never the protection you thought it was
- Watermarks applied in the browser, over an original that is still one request away
It is a maternity session, delivered in March, and the client asked for it to be private — you remember the conversation. In November she emails, and the email is short: her name and the phrase "maternity photos" put a thumbnail from her gallery on the second page of an image search, and she found it because a friend mentioned it. You go and look, and the app is behaving exactly as written: the gallery page asks for the password, and the password works. What you had forgotten is that the grid loads images directly from the bucket, at storage/galleries/hannah-m-maternity/preview/, because doing it any other way made a page of eleven hundred photographs feel slow on the test wedding. That prefix was never protected by anything but obscurity. A crawler found one link in a forwarded message on an indexed page, and object storage answered every request cheerfully, because that is what it does. You can fix the app in an hour. You cannot fix what is already in an index, or in the caches downstream of it, and you have no way to know what else was walked before you noticed — and the conversation you have to have next is with someone who told you, in March, that this mattered.
Is that you?
the verdict is a default, not a law
- Every image byte is served through a short-lived signed URL that the gate issues, with no public path anywhere in the storage layout
- It is your own work, delivered to a handful of clients you could phone, and the originals live somewhere else that is backed up
- Gallery URLs are long random tokens rather than slugs or sequential IDs, and they can be revoked and reissued in one action
- Nothing is collected from guests: no email gate, no download form, no analytics that stores who looked at what
- The gate protects the HTML page while the images live at a path anyone can construct from the gallery name
- Bucket listing is enabled, or you have not actually checked, which for a vibe-coded storage config is the same thing
- The gallery holds work where exposure is the harm — maternity, boudoir, children, anything a client explicitly asked to keep private
- You are collecting guest emails to unlock downloads and have no deletion path for them
- One password covers the whole gallery forever, with no expiry and no way to cut off access after it is forwarded
- You are hosting other photographers' galleries, because one misconfigured prefix then exposes several businesses at once
If you build it anyway
the checklist, then the prompt that enforces it
- Serve every byte through the gate. Images, thumbnails, previews and archives all come from short-lived signed URLs issued after the password check — no public object path, ever.
- Turn off bucket listing and verify it from a machine with no credentials. Then verify the preview and thumbnail prefixes separately, because those are the ones people forget.
- Make gallery URLs long random tokens, not names or numbers, and make revoking one a single action that invalidates outstanding signed URLs.
- Give passwords an expiry and a rotation path, and let the photographer see when a gallery was last opened so a forwarded link is at least visible.
- Set noindex headers on gallery pages and assume they will be ignored, because the real defence is that an unauthenticated request returns nothing.
- Strip EXIF from anything downloadable by default, and make keeping it a deliberate per-gallery choice made by a human.
- If you gate downloads on an email address, you have started collecting personal data — say so on the form, set a retention period, and build the deletion path before the first gallery goes live.
- Write down, per gallery, who it was delivered to and what the client asked for regarding privacy. That note is what tells you which galleries need the strictest settings.
I am building password-protected client photo galleries. The photographs are of
real people who asked for them to be private, and a leak cannot be undone. Put
the access model in place before the gallery exists, and refuse the shortcuts
that make a grid fast at the cost of the gate.
1. Access model first. Every image byte — original, download, preview and
thumbnail — is served through short-lived signed URLs issued only after the
gallery gate passes. No public object path exists at any point.
2. If I ask you to load images straight from a bucket path built from the
gallery name because the grid feels slow, refuse, and explain that this makes
the password protect the HTML and nothing else.
3. Storage config is part of this task: listing disabled, no public-read ACLs,
and a documented check I can run without credentials proving an anonymous
request is refused. Check the thumbnail prefix separately.
4. Gallery identifiers are long random tokens — never sequential IDs, never the
client's name. Revoking one invalidates outstanding signed URLs.
5. Passwords expire, rotate without rebuilding the gallery, and are checked
server-side with a constant-time comparison and a rate limit.
6. Strip EXIF by default from anything downloadable, and tell me that GPS in a
home shoot points at where the client lives.
7. Do not add an email-for-download gate unless I ask. If I do, add a retention
period, a consent line and a working deletion path in the same change.
8. Set noindex and a restrictive robots.txt, then tell me plainly that neither
is a security control — an unauthenticated request must return 403.
9. Log gallery access with timestamp and coarse location so I can see when a
link has clearly been forwarded. Show that to me, not to the client.
10. Build the archive download asynchronously from object storage with resume
support. Never stream a multi-gigabyte zip through the app process.
11. Out of scope: the print store and taking payments. Finish by telling me what
Pixieset costs and that its access model is what I am reimplementing.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 the photographs are of somebody who is not you. Ten dollars a month, or eight annually, buys an access model that has been attacked by strangers for a decade — which is the one component of this build where being 95% right is indistinguishable from being wrong, and where the person who pays for the last 5% is the client who asked you to keep it private. Build your own only for your own portfolio, and only after you have proved that an anonymous request for an image returns nothing.
$10/mo is cheaper than your weekend.
Keep the photographs in a bucket you control, organised by client and date in folders a human can read without your database, so the worst case is handing over a prefix and a set of credentials. What does not survive a migration is the access layer — gallery tokens, passwords, favourites, download records — so export a per-gallery JSON manifest on a schedule and keep a plain list of which galleries are live, who they were delivered to and when they should come down. If you shut the app off, the correct final act is not archiving it: it is confirming that every previously public URL now returns 403, because a gallery you stopped maintaining is still a gallery someone can find.
Self-hosted photo management with password-protected albums and share links, which is close to this exact product and has already made the access-control mistakes for you.
Active open-source self-hosted photo and video management platform.
Questions
How is this different from the Pic-Time entry?
Same product shape, different failure. Pic-Time's entry is about time — proofing selections that become the record of what was agreed, storage bills that grow against a one-off fee, and the client who comes back in year six. This one is about the gate: how a private gallery stops being private in week one, usually because the images were never behind the password in the first place. Both are YOUR FUNERAL; you meet them at opposite ends of the job.
Is a shared password ever good enough?
For a link you expect to be forwarded, it is roughly what everyone uses, and it is fine as long as it is genuinely the thing standing between an anonymous request and the bytes. The problem is never the password's strength — it is that it usually guards a page while the files sit somewhere else with no gate at all. Give it an expiry, make it rotatable, and check what an unauthenticated request for an image actually returns.
What is the single test that would have prevented most of this?
Open a private browser window with no session, take an image URL out of the network tab of a logged-in gallery, and request it. If you get a photograph back, the password is decorative. Do it for the thumbnail and preview paths too — those are generated separately and are where the leak most often is.
Does an email-for-download gate really count as collecting personal data?
Yes, and it is the part photographers add without thinking because it looks like marketing. Ninety guest addresses gathered under an implied purpose is a list you now hold, must secure, and must be able to delete from on request. If you want it, say what it is for on the form and build the deletion path in the same afternoon.
- GDPR Art. 5 — principles relating to processing of personal data (EU)
- GDPR Art. 32 — security of processing (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.
Every other program you write can be reinstalled. Your photo library is the only file set with no upstream copy.
You are not delivering photographs. You are promising a URL still resolves on their tenth anniversary.
A gallery that sells prints is a shop with a factory attached. The bad crop ships, and it ships to her mother.
last reviewed 2026-08-04 · verdict is editorial and unsponsored · shared entry data from canivibecodeit under MIT · not legal advice