Photo Album

Next.jsTypeScriptPostgreSQLNeonVercel BlobTailwind CSSView LiveView Code

A full-stack photo gallery and token-gated image API — a masonry gallery of ~1,100 images with infinite scroll, lightbox, and account-synced favorites, plus a documented REST API secured by hashed bearer tokens. Built on Next.js 16 with Neon Postgres and Vercel Blob, hosted entirely on Vercel with hand-rolled session + token auth (no third-party auth).

Photo Album is a full-stack photo gallery with a public, token-gated image API. The front end is a responsive masonry gallery of ~1,100 curated images with infinite scroll, a click-to-view lightbox, search, category filters, and account-synced favorites with global star counts. The back end is real — Neon Postgres for accounts, API tokens, and favorites; Vercel Blob for image storage — and the whole thing runs on Vercel with no AWS.

What sets it apart is that nothing is mocked: it ships hand-rolled auth (scrypt-hashed passwords, HMAC-signed session cookies) and a documented REST API where third parties authenticate with glr_-prefixed bearer tokens whose SHA-256 hashes are the only thing stored.

System Architecture

The gallery and API routes run in one Next.js app: session-cookie auth for the UI, hashed bearer tokens for the public API, with Postgres holding identity/metadata and Blob holding the image bytes.

drag nodes · click to highlight · scroll to zoom

Data Model

Three Postgres tables hang off the user; image bytes live in Blob, keyed from the favorites table by their public URL.

drag nodes · click to highlight · scroll to zoom

Public API

  • GET /api/images — bearer-token-gated; fetch images by count, category, name, or favorites / popular / random.
  • POST /api/images — bearer-token-gated; add an image by URL (JSON) or file (multipart).
  • GET /api/photos — public; the full collection the gallery renders.
  • /api/favorites, /api/tokens — session-cookie-gated; app-side favoriting and token management.
curl "https://photo-album-self.vercel.app/api/images?favorites=true&count=5" \
  -H "Authorization: Bearer glr_your_token_here"

Highlights

  • Masonry gallery — responsive columns with IntersectionObserver infinite scroll (48 per batch) and a lightbox.
  • Account-synced favorites — per-user stars plus global star counts, persisted in Postgres.
  • Hand-rolled auth — scrypt password hashing and HMAC-signed, HTTP-only session cookies; no auth provider.
  • Token-gated API + docsglr_ bearer tokens stored only as SHA-256 hashes, with an interactive docs page and curl examples.
  • All-Vercel stack — Next.js, Neon Postgres, and Vercel Blob with no AWS or external image host.

Tech

Next.js 16 (App Router) · React 19 · TypeScript · Tailwind v4 · Neon Postgres via @vercel/postgres (raw SQL) · Vercel Blob · Node crypto for scrypt + HMAC · react-masonry-css · Sharp. Deployed on Vercel.