Tracking Down Visual Assets Across Thousands of Repos

During the 2020 refresh of Shopify's design language, the Polaris team faced a problem that went beyond updating a few images. New illustrations, colors, and interface shapes had to be rolled out across a product ecosystem spanning more than 6,000 repositories. The hardest part was the illustration work: the previous style was lighthearted, but the new direction had to be direct and literal. Replacing every asset was a discovery problem more than a design problem.

An image showing the previous design language illustration style on the left which is more abstract representation of percentage discount and the updated illustration on the right which is more literal and shows a pair of scissors cutting a yellow rectangle with a % symbol in white text.
The previous design language illustration style on the left and the updated illustration on the right

Why Illustration Discovery Was So Difficult

The initial approach was manual. Illustrators walked through the Shopify admin, logged each image and its URL in a spreadsheet, and handed the list to developers for replacement. That worked, up to a point. The gaps appeared in the code itself: there was no easy way to tell which repository contained an illustration, how many times it was referenced, or whether it was being reused across multiple applications.

A browser window displaying the Shopify admin Discounts page illustration when no discounts have been created. The page title is Discount and has a navigation menu down the left hand side. The highlighted menu items is Discounts. The page shows and illustration of a yellow rectangle with the % symbol in white and a pair of scissors is cutting it. Below the image is text copy encouraging the user to create a discount code with a button labelled Create Discount Code below it.
Discounts page illustration when no discounts have been created.

A few factors made this genuinely messy. Illustrations were stored as PNG, SVG, PDF, or WebP with no consistent standard. Some images came from API requests rather than static files, placing them in server-side code. And because Shopify ships constantly, an illustration found in one browser session could be gone or changed the next. Many illustrations also only appeared in specific application states, like an empty state for shops without discounts or a homecard highlighting increased return rates. Manual browsing of the admin simply did not provide confidence that every asset had been found.

The team needed a tool that could:

  1. Locate images in repositories matching specific file extensions
  2. Identify the exact line of code where each image was referenced
  3. Expose the results through an API
  4. Provide a browsable interface with sorting and filtering

Nothing on the market fit, so they built it themselves.

The First Attempt: JavaScript and a Monorepo

The prototype used a Node.js script to clone repositories, then leveraged globby to locate matching image files. From there it scanned every file for usage references and saved the results to JSON. A json-server instance served the data to a lightweight Preact app that let illustrators visually search, sort, and filter the assets.

It worked, but it had serious limitations. The data was only as current as the last build, and each rebuild required cloning multiple repos and searching millions of lines of code. The Node.js file system (fs) library became a performance bottleneck, and after aggressive optimization the full search of 24 repositories still took over 35 minutes. For the illustrator team, the experience was frustrating: the data quickly went stale, running it locally required technical know-how, and adding a new repository to the search was far from simple.

Rewriting in Go

The team's comfort zone was JavaScript, and it had produced a tool that didn't meet its own quality bar for performance and accessibility. To fix that, they reframed the problem: "How can anyone generate a website to browse visual assets from any GitHub repository?"

They looked to tools like esbuild for inspiration, where thousands of file-based operations can be triggered by a single command. Go was the answer. It let them consolidate what had been a Preact site, an API server, and multiple Node.js scripts into one executable that could run reads in parallel across all CPU cores.

The architecture changed significantly. The monorepo disappeared; cloning, searching, building, and starting the application were all moved into a single Go binary. The Preact components were migrated to Next.js, and the separate API server was replaced by endpoints serving data directly from the JSON output.

The performance gains were dramatic: the same job that previously took over 35 minutes was reduced to 8 minutes, with the remaining time dominated by cloning monolithic repositories. The resulting tool, @shopify/get-repo-images, is now used across teams at Shopify for finding, removing, and updating images.

Open Source and Ready to Run

The Polaris team has released @shopify/get-repo-images as open source. It is a fast repository crawler designed for maintaining images across many codebases, written in Go for performance but runnable through npm for easy access. Its intended audience includes non-developers: illustrators and other team members can use it without a deep technical background.

Usage is straightforward:

After the search completes, the tool launches a local website at http://localhost:3000 for browsing, sorting, and filtering the results. The project is actively maintained by the Polaris team, with bug reports and pull requests accepted per the contribution guidelines in the repository.