Guides · Free · Photographers

BUILD YOUR
PHOTO SITE

The whole stack behind this site, step by step

This site has a tagged gallery, a private admin, a print shop that sends orders straight to a print lab, private client galleries, product feeds for Instagram, Pinterest and TikTok shopping, and pages built for Google and AI search. No monthly website platform, no commission on sales, and I own every line of the code. This guide is everything I learned building it, including what broke. Read it, or grab the AI playbook and have Claude or ChatGPT walk you through it.

Download the AI playbook ↓ Or have me build it →
00OverviewRead first

What you're building

You can stop at any step and still have a working site. Most people want the first three. The shop and the feeds are what turn it into something that sells.

  • Portfolio: a fast gallery with tag filters (city, subject, black and white, night) that loads well on phones.
  • Admin: a private page where you upload, title, tag, reorder and hide photos without touching code.
  • Print shop: buyers pick a size, pay with Stripe, and the order goes to a print lab that prints and ships it. You never handle a print.
  • Client galleries: a private link per shoot where clients see their photos, unlock downloads and order prints.
  • Shopping feeds: your catalog shows up as tagged products on Instagram, Pinterest and TikTok.
  • Search: one real page per photo, structured data, a sitemap and an llms.txt, so Google and AI assistants can find and cite your work.

What it costs

Hosting, database and payments all have free tiers that cover a new site. Plan on a domain (a yearly fee), a paid database tier once you go live (free tiers pause idle projects, more on that in step 13), and the standard card processing fee on each sale. Prints are paid for out of each order, so there's no inventory.

How long it takes

With an AI coding assistant doing the typing: a weekend for the portfolio and admin, another weekend or two for the shop, and a few evenings each for client galleries, feeds and SEO.

01Foundation~1 hour

The stack

  • Plain HTML, CSS and JavaScript. No framework needed. My whole front end started as one index.html. It loads fast and any AI assistant can edit it.
  • GitHub to hold the code, and Vercel to host it. Every push to GitHub redeploys the site. Preview branches give you a private test URL before anything goes live.
  • Supabase for the database (Postgres), file storage for photos, login for your admin, and small server functions.
  • Stripe for checkout. Stripe Checkout gives you Apple Pay, Google Pay and cards without building a payment form.
  • A print-on-demand lab with an API. I use Prodigi. It prints fine art paper, framed and canvas, and ships from labs in several countries.
  • An AI coding assistant. I use Claude Code, which edits the files on your computer directly. A chat assistant works too; you'll copy and paste more.

Why not Squarespace, Pixieset or SmugMug? They're fine and faster to start. You trade a monthly fee, someone else's templates and limits on what you can automate. Building your own lets you do things like push your whole catalog to Instagram Shopping automatically, which most platforms can't.

02Setup~2 hours

Accounts and domain

  1. Buy your domain. Your name is best.
  2. Create a GitHub account and a new repository for the site.
  3. Create a Vercel account, import the repository, and add your domain in the project's domain settings. Vercel shows you the DNS records to set at your registrar.
  4. Create a Supabase project. Note the project URL and the public (anon) key.
  5. Create a Stripe account. Stay in test mode until your first test order works end to end.
  6. Create a Prodigi account (or your lab of choice) and get a sandbox API key.

Keys: the one rule that matters

Public keys (Supabase anon key, Stripe publishable key) can live in your page. Secret keys never go in the page. That's the Supabase service role key, the Stripe secret key, the Stripe webhook secret and the lab API key. They go in environment variables in Vercel or Supabase, and only server functions read them. Don't paste secret keys into an AI chat either. Tell the assistant the variable name and add the value yourself.

Not your thing? I'll build it for you →
04Files~half day

Image pipeline

Every photo needs two files:

  • Web version: around 2000 to 2400 pixels on the long edge, compressed to a few hundred KB. This is what the gallery shows.
  • Master: the full-resolution export, kept private, used only for prints.

Have your upload resize and compress the web version in the browser before it uploads, so you can drop in full-size exports and never think about it.

What broke for me

Twice, new photos just never showed up in the gallery. The cause both times was oversized web files that failed silently. Build the resize into the upload so it can't happen, and have the uploader tell you when something fails.

Privacy

Camera and phone files carry GPS coordinates. Strip location data from every public file. If you want to show where a photo was taken, put the city in the title and tags yourself.

05Management~1 day

Private admin

This is the page that makes the site something you'll actually keep updating. Mine does bulk upload with drag and drop, tag editing, reordering, hiding, marking photos for sale, and an analytics panel.

Lock it down properly

  • Use Supabase Auth for your login (email link or password), not a password checked in JavaScript. Anything in the page can be read by anyone who opens developer tools.
  • Turn on Row Level Security for every table. Write policies so anyone can read visible photos, but only your logged-in user can insert, update or delete.
  • Give the admin its own route and mark it noindex. Don't link it from anywhere public.
What broke for me

My first admin panel's upload form shipped to every visitor, just hidden with CSS. It was harmless because the database rules held, but it's the wrong pattern. Load admin code only after login.

Rather skip the setup? Get a quote →
06Findabilityongoing

Titles, tags, metadata

This is the boring step that does the most for search and sales. "IMG_4471" sells nothing. "Eiffel Tower at Night, Paris, France" gets found.

  • Titles: landmark or subject, then place. Same pattern every time.
  • Tags: keep a fixed vocabulary. Places (city, country), subjects (architecture, concerts, ocean), style (black and white, long exposure), time (day, night).
  • Alt text: one plain sentence describing the photo, for accessibility and image search.
  • Let AI do the first pass. An AI model can look at each photo and draft a title, tags and alt text. Then you fix what it gets wrong. Much faster than starting from blank.
  • Sets: group photos into named collections (a city, a trip, a series). They make browsing easier, and they double as product groups in your shopping feeds.
07Selling~1 to 2 weekends

Print shop

How an order flows

buyer picks photo + size + finish
  → your server function creates a Stripe Checkout session
  → buyer pays on Stripe
  → Stripe calls your webhook
  → webhook checks the payment is real, then places the
    print order with the lab, using a signed link to the master
  → lab prints and ships, sends tracking
  → buyer lands on your thank-you page

Rules that keep prints looking right

  • Only offer sizes that match each photo's aspect ratio. A 3:2 photo gets 4x6, 8x12, 16x24, 24x36. A 4:3 photo gets 6x8, 9x12, 12x16. Nobody gets a surprise crop.
  • Set a resolution floor. I only offer a size if the master has at least 200 pixels per inch at that size. Smaller files get smaller sizes.
  • Store the width and height of every master so the site can work out both of those on its own.

Pricing

Pull print cost and shipping from the lab's quote API instead of typing them in. Prices change and shipping varies by country. Then price to the margin you want:

price = (print cost + shipping) / (1 - target margin)

$30 cost, 45% margin → 30 / 0.55 = $54.55 → round to $55

I build shipping into the price and show "free shipping." Add a bulk discount for multiple prints, and sell sets of three or more as a bundle.

Test it for real

Run a complete order in Stripe test mode against the lab's sandbox. Then place one real order to your own address before you tell anyone the shop is open. You'll want to see the print quality yourself anyway.

What broke for me

People who tap your link inside Instagram land in Instagram's built-in browser, which has no Apple Pay. Detect it and show a small bar offering to open the page in Safari or Chrome.

Want a shop without the plumbing? I'll set it up →
08Clients~1 weekend

Client galleries

If you shoot for clients, deliver through your own site instead of a separate gallery service. It looks more professional and it's one more reason people end up on your domain.

  • Each shoot gets a private link with an access code, like /g/smith-family?code=7K2Q. The server checks the code before sending any photos.
  • The client unlocks their included photos for download, can buy extra unlocks, and can order prints of anything unlocked through the same shop.
  • Mark these pages noindex and keep them out of your sitemap, product feeds and search pages. Serve photos through signed links that expire.
  • Add a way for clients to request edits on a specific photo. It saves a lot of back and forth.
My rule

Client photos are never for sale to the public. They're the client's. With permission, I only use them to show my work.

09Trust~2 hours

Policy pages

Put these up before you connect any shopping platform. Pinterest rejected my merchant application until I had them.

  • Shipping and returns: where you ship, how long it takes, what happens with damaged or wrong prints.
  • Contact: a form, not your personal email. Published emails get spammed.
  • Privacy: what you collect (contact form, analytics, orders) and who processes it (Stripe, the print lab).

Sales tax: prints are physical goods, and most US states tax them once your sales pass a threshold. Look up your state's rules, and talk to an accountant if you're unsure. This guide isn't tax advice.

10Reach~1 to 2 days

Instagram, Pinterest, TikTok

Every shopping platform takes a product catalog, which is just a spreadsheet or feed of your products: ID, title, description, price, image URL, product page link, availability. Since every photo already lives in your database, a small script can generate those feeds automatically.

  • Meta Commerce Manager for Instagram and Facebook Shops. Lets you tag prints in posts and reels.
  • Pinterest catalogs turn every print into a shoppable pin.
  • TikTok Shop / catalog works the same way.
  • Google Merchant Center gets your prints into Google Shopping results.

Use your sets as product groups so related photos stay together. Regenerate the feeds whenever you add photos, or have the platform fetch them from a URL on a schedule.

11Search~1 day

SEO and AI search

A gallery built with JavaScript can look like an empty page to a search engine. Give every photo a real page.

  • One static page per photo (/print/eiffel-tower-night-paris), generated by a script at deploy time, with the title, description, sizes and prices in plain HTML.
  • Structured data on each page: schema.org VisualArtwork and Product with offers and prices. This is how Google shows prices and images in results.
  • sitemap.xml listing every public page, generated from the database. Submit it in Google Search Console.
  • llms.txt at the root: a plain-language summary of who you are, what you sell and how pricing works. AI assistants read it.
  • A JSON catalog (/catalog.json) so agents and tools can read your whole catalog in one request.
  • Link previews: Open Graph tags and a preview image on every page, so shared links look good in texts and DMs.
What broke for me

A redesign quietly dropped my page titles and descriptions, and I didn't notice for weeks. After any big change, check a few pages with a link preview tool and Google's Rich Results Test.

12Measure~half day

Analytics

Vercel's built-in analytics covers the basics. I also log my own events (page views, photo opens, size picks, checkout starts) to a Supabase table and chart them in my admin, so I can see exactly where buyers drop off.

  • Exclude yourself. Set a flag in your browser when you log into the admin and skip tracking when it's there. Otherwise your own testing becomes your biggest "customer."
  • Filter out bots and crawlers, or your numbers will look much better than they are.
  • Watch the funnel, not just visits: views → product opens → size picked → checkout → paid.
13Shipchecklist

Launch and upkeep

Before launch

  • Domain loads over HTTPS, with and without www.
  • Gallery, filters and photo pages look right on a phone.
  • Admin requires login. Logged out, you can't write anything to the database.
  • Full test order in test mode, then one real order to yourself.
  • Policy pages are live and linked in the footer.
  • Sitemap submitted, link previews checked, analytics excluding you.

Keeping it running

  • Move the database to a paid tier once you're live. Free projects pause when idle, and a quiet portfolio site will hit that. Your gallery just goes blank.
  • Add a free uptime monitor that checks your gallery actually loads photos, not just that the page returns.
  • Back up the database and your masters somewhere you control.
  • Make changes on a preview branch, check them on your phone, then merge to live.
  • Re-check lab prices and shipping every few months so your margins hold.
What broke for me

My gallery went down because the database hung, not because anything in the site changed. That's exactly what an uptime check would have caught before a visitor did.

Free download · Works with Claude or ChatGPT

The AI playbook

A text file that turns an AI assistant into a build partner for this exact site. Paste it into Claude, ChatGPT or another assistant (or drop it into a Claude Code project). It interviews you about what you shoot and what you want, then walks you through every step above one at a time, checks your work, and keeps you away from the security mistakes. If your assistant can edit files, it can do most of the typing.

Download playbook (.txt) ↓
→ToolsOptions

Gear: what I use and the alternatives

You don't need any of this to build the site. It's what I shoot with and use to get photos from camera to print. Each slot has a budget, a pick and an upgrade, with what each is best for. "I use this" marks gear I own. Links open on Amazon.

Done for you

Rather not build it yourself?

I build these for photographers: your photos, your brand, your domain, and accounts in your name, so you own everything. Pick what you want and I'll send you a quote.

Disclosure: As an Amazon Associate I earn from qualifying purchases. Product links on this page are affiliate links. Items marked "I use this" are gear I own; the rest are options I researched. The price you pay is the same. Other services named in this guide (Vercel, Supabase, Stripe, Prodigi, Claude) are mentioned because I use them, not because they pay me.