The gallery half of SmugMug is a weekend: originals in a bucket or on a disk, resized copies, a portfolio page, unlisted client galleries with a password and a streamed zip download. An agent builds that in a day, and storage is the only recurring cost. What a copy lacks is everything that turns photos into income: print orders sent to labs, card payments with tax handled, a Lightroom publish plugin, and phone apps that upload on their own. Photographers who only deliver files to clients can replace it; photographers who sell prints can't, short of rebuilding a storefront.
Before you buildSmugMug has no free plan. If you only deliver files to a few clients, a hosted gallery with a free tier may cost less than running this.
Build me a personal photo gallery and client-delivery site to replace SmugMug. Requirements: - Node.js 22 + TypeScript: a Fastify server with server-rendered pages (Eta) and a little vanilla JS. `npm start` serves http://localhost:4900: the portfolio at /, galleries at /g/<slug>, admin at /admin. - Storage: better-sqlite3 in ./data/gallery.db for folders, galleries, photos (EXIF date, width, height, bytes) and share tokens. Originals stay untouched in STORAGE_DIR (default ./data/originals/), or in an S3-compatible bucket (`@aws-sdk/client-s3`) when S3_BUCKET and its keys are set in .env. - Processing: on upload, `sharp` writes 400 px and 1600 px WebP copies and `exifr` reads the EXIF date; `npm run import <folder>` ingests a folder tree, one gallery per folder, skipping files already imported (hash of the original). - Public pages: a portfolio of galleries I mark featured, a lazy-loaded grid per gallery and a lightbox with arrow-key navigation; every page works without JS except the lightbox. - Client galleries: unlisted, reached by a random 32-byte token in the URL, with an optional password (argon2) and an expiry date; clients can heart photos and I can copy the favourites as a list of filenames to paste into Lightroom. - Delivery: a "download all" button streams a zip (`archiver`) of the originals or of the 1600 px copies, switchable per gallery; downloads can be turned off. - Admin: one password in .env (signed cookie), drag-and-drop upload, reorder, cover photo, delete. - Single user. No accounts, no telemetry, local-first: the only outbound calls go to your bucket. - Out of scope: print sales and lab fulfilment, card payments and tax, RAW files, a Lightroom plugin, a mobile app. - README: HTTPS with Caddy, creating the bucket, and a warning that the originals live only in that folder or bucket, so you need your own backup.
Opens your agent with the prompt filled in, you press enter. Or copy it and paste it into an empty folder.
The first prompt builds the core. Run these one at a time in the same folder to grow it into your own SmugMug.
Add a SmugMug importer to the gallery site in this folder. Requirements: - A command `npm run import:smugmug <folder>` that reads a folder tree downloaded from SmugMug (the Smudo or Folio layout: one folder per gallery, nested folders for categories). - Create folders and galleries named after the directories, keep the original filenames and capture dates, and skip files whose hash is already in the database. - Print a summary of new, skipped and unreadable files before writing, and require --yes to proceed. - Mark every imported gallery as unlisted so nothing becomes public by accident. - Update the README with how to download the library from SmugMug first.
Add client proofing to the gallery site in this folder. Requirements: - In a client gallery, a heart on each photo stores the choice against the gallery token in SQLite, with a cap per gallery that I set (for example 40 photos). - A "Send selection" button locks the picks and emails me the filenames through nodemailer (SMTP in .env). - In admin, show picks per gallery, let me unlock the selection, and export it as a text file of filenames and as a CSV. - Rate-limit the heart endpoint per token and ignore requests for photos outside the gallery. - Update the README.
Add paid digital downloads to the gallery site in this folder. Requirements: - Per gallery, an optional price per photo or for the whole gallery, stored in cents. - Checkout through Stripe Checkout (`stripe` package, STRIPE_SECRET_KEY and STRIPE_WEBHOOK_SECRET in .env), with a webhook that verifies the signature before it marks an order paid. - After payment, issue a download link that expires after 48 hours and allows five downloads. - An orders page in admin; refunds stay in the Stripe dashboard. - State in the README that taxes and receipts are my responsibility and Stripe Tax is opt-in.
Photographers pay for work they would rather not do: keeping years of originals safe, showing a clean site to clients, and having print orders handled from payment to delivery without touching them. A client who can't open a gallery costs more than the subscription, so the reliable, boring service is the product.
Estimate · Free on a home server and a spare disk. A $5 VPS plus object storage for a terabyte or two lands near $20; storage is the cost that grows. The build is token usage on your agent plan.
| Plan | Monthly | Annual, per month | What you get |
|---|---|---|---|
| Direct | $29 | $20 | Unlimited full-resolution JPEG storage, privacy controls, digital delivery of galleries, Lightroom integration, 24/7 live support. |
| Portfolio | $35.50 | $23.50 | Direct plus website templates, print and digital-download sales with lab fulfilment, watermarks and theft protection, set-your-own profit margins. |
| Pro | $52 | $37 | Portfolio plus multiple pricelists, coupons and packages, client favouriting, download limits. |
| Enterprise | custom | — | Tailor-made plan for studios, teams and institutions. |
No free plan; every plan starts with a 14-day trial of all features.
Kinda. The core is a weekend build with the prompt on this page, but real gaps remain: Print and product sales through lab partners, with orders fulfilled for you, Card payments with automatic tax collection and receipts.
About $29 a month on the Direct plan, $348 a year (checked 2026-10-19).
Print and product sales through lab partners, with orders fulfilled for you; Card payments with automatic tax collection and receipts; The Lightroom publish service and phone apps that upload automatically; Storage you never think about and a support team that answers at any hour; Professional website templates and a shop front. If any of those matter to you, keep paying.
Yes: Lychee (open source), Piwigo (open source), PiGallery 2 (open source).