we’ll make Admin-only uploading for Stock Photos and Mockups, and have the public pages auto-populate from those libraries.

Below is a tight, working setup: minimal DB (JSON files), file uploads, role-guarded admin endpoints, and simple UI pages.

Backend (Express)
0) Install
npm i express multer sharp

1) Routes: Stock Photos & Mockups

Create server/api/stock/library.ts:

import { Router } from "express";
import multer from "multer";
import fs from "fs/promises";
import path from "path";
import { authWithKey, requireRole } from "../../middleware/auth";

const router = Router();

// File storage (local). Replit: persist /uploads in your project.
const UP = (sub: string) => path.join(process.cwd(), "uploads", sub);
const DB = (name: string) => path.join(process.cwd(), "tmp", `${name}.json`);

const photosDir = UP("photos");
const mockupsDir = UP("mockups");

async function ensure() {
  await fs.mkdir(photosDir, { recursive: true });
  await fs.mkdir(mockupsDir, { recursive: true });
  await fs.mkdir(path.join(process.cwd(), "tmp"), { recursive: true });
  try { await fs.access(DB("photos-db")); } catch { await fs.writeFile(DB("photos-db"), "[]"); }
  try { await fs.access(DB("mockups-db")); } catch { await fs.writeFile(DB("mockups-db"), "[]"); }
}

type Item = {
  id: string;
  url: string;        // public path
  w?: number; h?: number;
  name: string;
  tags: string[];
  category?: string;  // e.g., “office”, “tech”, “lifestyle”
  createdAt: number;
};

const upload = multer({
  storage: multer.diskStorage({
    destination: async (req, file, cb) => {
      await ensure();
      const isMockup = (req.path.includes("/mockups"));
      cb(null, isMockup ? mockupsDir : photosDir);
    },
    filename: (_req, file, cb) => {
      const ts = Date.now();
      const safe = file.originalname.replace(/[^a-zA-Z0-9._-]/g, "_");
      cb(null, `${ts}-${safe}`);
    }
  }),
  limits: { fileSize: 25 * 1024 * 1024 }, // 25 MB
});

// ---------- Admin upload ----------
router.post("/photos",
  authWithKey, requireRole("owner","manager"),
  upload.array("files", 50),
  async (req, res) => {
    await ensure();
    const body = req.body || {};
    const tags = (body.tags || "").split(",").map((t: string)=>t.trim()).filter(Boolean);
    const category = (body.category || "").trim() || undefined;

    const dbPath = DB("photos-db");
    const db: Item[] = JSON.parse(await fs.readFile(dbPath, "utf-8"));

    const items: Item[] = (req.files as Express.Multer.File[]).map((f) => ({
      id: `${Date.now()}_${Math.random().toString(36).slice(2,8)}`,
      url: `/uploads/photos/${path.basename(f.path)}`,
      name: f.originalname,
      tags,
      category,
      createdAt: Date.now(),
    }));

    await fs.writeFile(dbPath, JSON.stringify([...items, ...db], null, 2));
    res.json({ ok: true, added: items.length });
  }
);

router.post("/mockups",
  authWithKey, requireRole("owner","manager"),
  upload.array("files", 50),
  async (req, res) => {
    await ensure();
    const body = req.body || {};
    const tags = (body.tags || "").split(",").map((t: string)=>t.trim()).filter(Boolean);
    const category = (body.category || "").trim() || undefined;

    const dbPath = DB("mockups-db");
    const db: Item[] = JSON.parse(await fs.readFile(dbPath, "utf-8"));

    const items: Item[] = (req.files as Express.Multer.File[]).map((f) => ({
      id: `${Date.now()}_${Math.random().toString(36).slice(2,8)}`,
      url: `/uploads/mockups/${path.basename(f.path)}`,
      name: f.originalname,
      tags,
      category,
      createdAt: Date.now(),
    }));

    await fs.writeFile(dbPath, JSON.stringify([...items, ...db], null, 2));
    res.json({ ok: true, added: items.length });
  }
);

// ---------- Admin delete (optional) ----------
router.delete("/:kind/:id",
  authWithKey, requireRole("owner","manager"),
  async (req, res) => {
    await ensure();
    const kind = req.params.kind === "mockups" ? "mockups" : "photos";
    const dbPath = DB(kind === "mockups" ? "mockups-db" : "photos-db");
    const list: Item[] = JSON.parse(await fs.readFile(dbPath, "utf-8"));
    const item = list.find((x) => x.id === req.params.id);
    if (!item) return res.status(404).json({ error: "Not found" });

    // remove file
    const dir = kind === "mockups" ? mockupsDir : photosDir;
    const filename = path.basename(item.url);
    try { await fs.unlink(path.join(dir, filename)); } catch {}

    const next = list.filter((x) => x.id !== req.params.id);
    await fs.writeFile(dbPath, JSON.stringify(next, null, 2));
    res.json({ ok: true });
  }
);

// ---------- Public list ----------
router.get("/photos", async (_req, res) => {
  await ensure();
  const dbPath = DB("photos-db");
  const list: Item[] = JSON.parse(await fs.readFile(dbPath, "utf-8"));
  res.json(list);
});

router.get("/mockups", async (_req, res) => {
  await ensure();
  const dbPath = DB("mockups-db");
  const list: Item[] = JSON.parse(await fs.readFile(dbPath, "utf-8"));
  res.json(list);
});

export default router;