Image Upload & Thumbnails Tutorial · Module 07 of 11

Search, Tags & Collections

Add image tagging, full-text search, and collections/albums. Users organize images by tags and group them into collections. Search by tags, metadata, or filename. By the end, users can discover and organize their image library effectively.

~4–5 hrsIntermediateOrganization focus
← Back to Module 07 overview
What You'll Have at the End

Definition of Done

  • POST /images/:id/tags — add tags to image.
  • GET /search?q=...&tags=...&collection=... — full-text search.
  • POST /collections — create collection/album.
  • POST /collections/:id/images — add image to collection.
  • GET /collections/:id/images — list collection images.
  • Full-text search on filename and tags using PostgreSQL.
  • Tags table: images_tags junction table with tag_id and image_id.
  • Collections with display metadata (cover image, count).
The Steps

Build It

STEP 1

Design tagging and search schema

Create database tables in src/db/schema.sql:

CREATE TABLE IF NOT EXISTS tags (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  name TEXT NOT NULL UNIQUE,
  created_at TIMESTAMP DEFAULT NOW()
);

CREATE TABLE IF NOT EXISTS image_tags (
  image_id UUID REFERENCES images(id) ON DELETE CASCADE,
  tag_id UUID REFERENCES tags(id) ON DELETE CASCADE,
  PRIMARY KEY (image_id, tag_id)
);

CREATE TABLE IF NOT EXISTS collections (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  name TEXT NOT NULL,
  description TEXT,
  cover_image_id UUID REFERENCES images(id) ON DELETE SET NULL,
  created_at TIMESTAMP DEFAULT NOW(),
  updated_at TIMESTAMP DEFAULT NOW()
);

CREATE TABLE IF NOT EXISTS collection_images (
  collection_id UUID REFERENCES collections(id) ON DELETE CASCADE,
  image_id UUID REFERENCES images(id) ON DELETE CASCADE,
  PRIMARY KEY (collection_id, image_id)
);

CREATE INDEX idx_image_tags_tag ON image_tags(tag_id);
CREATE INDEX idx_collections_name ON collections(name);