# Gallery Setup Guide — Cloudinary

The gallery system (`gallery.html` for visitors, `admin-upload.html` for Brian)
runs on Cloudinary — a free image hosting service that handles storage,
auto-resizing, and delivery. Nothing needs to be installed; it's all free
signup + a few settings.

## 1. Create a free Cloudinary account

Go to **cloudinary.com** → sign up (free tier is generous — 25GB storage,
25GB bandwidth/month, plenty for a small business gallery).

Once logged in, your **Dashboard** shows a **Cloud Name** near the top —
a short slug like `dxk3ptmzq`. Copy it.

## 2. Turn on public listing by tag

By default Cloudinary blocks the browser from listing images by tag, for
security. The gallery page needs this on to work.

Go to **Settings → Security**, scroll to **Restricted media types /
Resource list**, and enable **"Resource list"** (sometimes labelled
"Allow listing of resources"). Save.

## 3. Create an unsigned upload preset

This lets Brian's upload page send photos to Cloudinary without needing a
server or a secret key.

1. **Settings → Upload → Upload presets → Add upload preset**
2. Set **Signing Mode** to **Unsigned**
3. Give it a name you'll remember, e.g. `classicforge_gallery`
4. Under **Upload Manipulations** (or **Incoming Transformation**, wording
   varies by account), add a transformation so every photo auto-resizes
   on the way in — e.g. **Crop mode: Limit, Width: 2000, Height: 2000**.
   This is the "auto resized" part — Cloudinary does it for every upload
   without Brian having to do anything.
5. Save. Copy the preset name.

## 4. Drop your details into the two files

**`gallery.html`** — near the bottom, find:
```js
var CLOUD_NAME = "YOUR_CLOUD_NAME";
```
Replace with your real cloud name from step 1.

**`admin-upload.html`** — near the bottom, find:
```js
var CLOUD_NAME = "YOUR_CLOUD_NAME";
var UPLOAD_PRESET = "YOUR_UPLOAD_PRESET";
var ACCESS_CODE = "classicforge2026";
```
Replace the first two with your real values from steps 1 and 3.
**Change `ACCESS_CODE`** to something only Brian knows — this is a light
deterrent, not real security (it's plain text in the page, since there's
no server to check it against). Don't reuse a real password, and don't
link this page anywhere public — it's deliberately not in the site nav
or footer. Give Brian the direct URL:

```
https://theclassicforge.co.za/admin-upload.html
```

## 5. How the category tagging works

Every photo Brian uploads gets two tags automatically: the category he
picked (e.g. `classicforge_steelwork`) and a catch-all tag
(`classicforge_all`). The gallery page's filter buttons just ask
Cloudinary for photos matching one of those tags — so a new upload shows
up in "All Photos" and its specific category filter within a minute or
two, no manual work needed beyond picking the category at upload time.

If you ever want a sixth category, add a new `<option>` in
`admin-upload.html`'s category dropdown and a matching filter button in
`gallery.html` — just keep the tag names consistent between the two
(`classicforge_yourcategory`).

## 6. Testing it

Once the four values above are filled in:
1. Open `admin-upload.html`, enter your access code, pick a category,
   upload a test photo.
2. Open `gallery.html` — within a minute it should appear under "All
   Photos" and under the category you chose.

If the gallery stays empty, double-check step 2 (Resource list) — that's
the most common thing left off.

## 7. Site Images — replacing heroes, category photos, etc.

Beyond the Gallery page, `admin-upload.html` has a second tab called
**Site Images**. This covers the 52 fixed photos used across the rest of
the site — every page hero, every service category photo, the homepage
process strip, the featured projects, and Brian's photos on the About
page.

**How it works:** each of those photos has a hidden label (like
`site-homepage-hero`) baked into the page. When Brian uploads a
replacement through the Site Images tab, it's tagged with that same
label. Every page checks Cloudinary for the newest photo carrying its
label and swaps to it automatically — no code changes, ever.

**The trade-off:** this uses the same public tag-listing feature as the
Gallery (step 2 above), and Cloudinary caches that list for **up to
one hour**. So a new upload can take up to an hour to actually appear
on the live site. That's a real limit of the free, no-server approach —
not a bug. If it's still showing the old photo after an hour, check
that the upload actually succeeded (the button should read "Uploaded ✓"
briefly) and that step 2's Resource List setting is still enabled.

**Nothing ever breaks in the meantime.** If a photo hasn't been
replaced yet, or a request fails for any reason (e.g. no internet), the
page just keeps showing its original static photo — visitors never see
a broken image.

**Adding a new slot later** (e.g. a new hero for a page you add): give
the `<img>` tag a `data-cf-slot="your-slug"` attribute in the HTML, then
add a matching entry to the `SITE_IMAGE_SLOTS` list near the bottom of
`admin-upload.html` so it shows up in the picker. The slug just needs to
match in both places.
