Case study — 2024

Brand Asset Library

Context

My long-time pharma aesthetics client again. Six product brands. Lots of media — images, video, social posts, before-and-after shots, in-office materials.

Brand asset library screenshot

Two audiences:

  • Brand managers — add content without calling a developer
  • Field teams and HCPs — healthcare professionals find and download what they need, no training

Why WordPress for the backend

The team already knew WordPress. Non-technical staff could add a resource, attach files, pick a brand and media type, and publish — no code.

Two taxonomies:

  • Brands — six product lines
  • Media Types — Banner, Before and After, Celebrity, Image, In-Office Material, Social Media, Video

The front-end

React, React Router, React Bootstrap, Vite.

A useResources hook fetches from the WordPress REST API, applies filters, and keeps results in sync as you move between brands and media types.

Filtering:

  • Pick a brand — narrows to one product line
  • Toggle media types — refines within that brand
  • Sort by most recent or most downloaded

The REST API is fast enough that it feels native even with bigger result sets. I also found a wordpress plugin which caches the responses to make it even speedier.

The download

Each tile has a download button. One resource can have multiple files — image, PDF spec sheet, video.

I made a custom REST route in a WordPress plugin. Front-end sends the resource post ID. The plugin:

  1. Retrieves all media attached to that post
  2. Fetches each file from the filesystem
  3. Assembles a ZipArchive in PHP
  4. Streams the zip to the browser with the correct Content-Type and Content-Disposition headers
  5. Increments a download count field in the post's meta
$media_ids = get_post_meta($post_id, 'resource_files', true);

foreach ($media_ids as $media_id) {
    $file_path = get_attached_file($media_id);
    $zip->addFile($file_path, basename($file_path));
}

Server-side streaming = normal file download. One request, one response.

What I'd do differently

Download count increments in the same request as the zip. Failed or interrupted downloads still bump the count.

Better: a separate lightweight endpoint the front-end hits only after the download finishes. Fine for rough internal usage tracking. Not fine if you need accurate analytics.

That being said, we did add Google Analytics to track downloads and other events, and they ended up getting rid of the front-facing count tally.

Bonus! Demo

So when I was bored the other day, I updated this asset repo to instead contain a fictional beer collective.

One day I shall discover the elusive 403 Forbidden Lager. Cheers! 🍻

My fictional beer collective portfolio
My fictional beer collective portfolio

View demo - Really Slow Spirits Collective