Serving Images in a Two-Repo, Rebuild-Free

June 2, 2025 (2mo ago)

The Nerdy Way

So, you’ve got your two-repo setup humming along.
You’re writing MDX, syncing content, and your site isn’t rebuilding for every typo.

But then you try to add an image to your blog post and…

Nothing shows up.
Or worse, you’re told to “just put images in public/.”

But that’s not the point, is it?


The Image Problem

I want to:


The Solution: Custom Image Route

Here’s how I solved it (and how you can too):

  1. Keep your images in your content repo
    Example: blogs/blog-images/my-cool-diagram.png

  2. Sync them over to your deployed repo
    Just like your .mdx files, your GitHub Action copies images into:

    synced-content/blogs/blog-images/
    
  3. Add a custom Next.js route
    I created a file route at:

    /blog-images/[...path]
    

    that streams images directly from synced-content/blogs/blog-images/

No copying to public/, no build bloat, no drama.

+-------------------+         GitHub Action         +---------------------+
|   Content Repo    |  ------------------------->   |   Portfolio Repo    |
|  (MDX + Images)   |   (sync .mdx + images)        |  (Next.js + Route)  |
+-------------------+                               +---------------------+
         |                                                    |
         |  ![img](/blog-images/my-cool-diagram.png)           |
         |                                                    |
         +-------------------[User Requests Image]------------+
                                         |
                                         v
                        +-----------------------------------+
                        |  /blog-images/[...path] Route     |
                        |  (Streams from synced-content/)   |
                        +-----------------------------------+
                                         |
                                         v
                                [Image served to browser]

How to Use It

In your MDX, reference images like this:

![My diagram](/blog-images/my-cool-diagram.png)
![Funny gif](/blog-images/memes/that-feeling.gif)

That’s it.

The route serves them up with proper content type and caching.
Works for .png, .jpg, .gif, .webp, .svg, you name it.


Why This Is Awesome


🤓 Bonus Nerd Points


Final Thoughts

This is what I love about building with Git and Next.js:

You can keep things simple, but still get all the power and flexibility you want.

If you’re tired of fighting your build system, or you want your content repo to be the single source of truth:

Serve your images the nerdy way.
Sync, route, and geek out.