Skip to content

Missing support for remote image configuration at the content-layer #15417

@erkobridee

Description

@erkobridee

Astro Info

Astro                    v5.17.1
Vite                     v6.4.1
Node                     v22.20.0
System                   Linux (x64)
Package Manager          npm
Output                   static
Adapter                  none
Integrations             @astrojs/mdx (v4.3.13)

If this issue only occurs in one browser, which browser is a problem?

No response

Describe the Bug

Consuming data from Strapi CMS, where a blog post is defined as markdown content, which contains images defined at the Strapi CMS, and the content is loaded by a custom loader ( renderMarkdown | Astro Docs )

Remote images configured: astro.config.ts

  image: {
    remotePatterns: [{
      protocol: 'http',
      hostname: 'localhost',
      port: '1337',
      pathname: '/uploads/**'
    }]
  },

This configuration is not passed into the content-layer.ts > createMarkdownProcessor line 144 like it happens on vite-plugin-markdown/index.ts > createMarkdownProcessor line 64

The Strapi CMS custom loader that I have defined in the project src/utils/strapi/loader.ts, case of usage to define a blogs collection src/content/schemas/blogs.ts

Blog post rendered by the Astro component: src/pages/[locale]/blogs/[slug].astro
Blog post example: https://erkobridee.com/strapicms-astro-client/en/blogs/content-with-images/

Blog post entry loaded from the blogs Astro content collection

{
  "id": "en/kr09fpwvi4t8lrhejpic5pbk",
  "data": {
    "id": 31,
    "documentId": "kr09fpwvi4t8lrhejpic5pbk",
    "createdAt": "2026-01-27T08:59:24.398Z",
    "updatedAt": "2026-01-27T10:49:20.114Z",
    "publishedAt": "2026-01-27T10:49:20.136Z",
    "title": "Content with images",
    "slug": "content-with-images",
    "description": "Testing a blog post that has images on its content",
    "body": "Lorem ipsum dolor sit amet consectetur adipiscing elit. Quisque faucibus ex sapien vitae pellentesque sem placerat. In id cursus mi pretium tellus duis convallis. Tempus leo eu aenean sed diam urna tempor. Pulvinar vivamus fringilla lacus nec metus bibendum egestas. Iaculis massa nisl malesuada lacinia integer nunc posuere. Ut hendrerit semper vel class aptent taciti sociosqu. Ad litora torquent per conubia nostra inceptos himenaeos.\n\n![this-shrimp-is-awesome.jpg](/uploads/this_shrimp_is_awesome_9c30d9f773.jpg)\n\n\nStet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.\n\n![we-love-pizza.jpg](/uploads/we_love_pizza_8452b56f30.jpg)\n\n\nend of the blog post",
    "cover": null,
    "coverAltText": null,
    "locale": "en",
    // ... supressed ...
  },
  "digest": "8363289eab4610e0",
  "rendered": {
    "html": "<p>Lorem ipsum dolor sit amet consectetur adipiscing elit. Quisque faucibus ex sapien vitae pellentesque sem placerat. In id cursus mi pretium tellus duis convallis. Tempus leo eu aenean sed diam urna tempor. Pulvinar vivamus fringilla lacus nec metus bibendum egestas. Iaculis massa nisl malesuada lacinia integer nunc posuere. Ut hendrerit semper vel class aptent taciti sociosqu. Ad litora torquent per conubia nostra inceptos himenaeos.</p>\n<p><img src=\"http://localhost:1337/uploads/this_shrimp_is_awesome_9c30d9f773.jpg\" alt=\"this-shrimp-is-awesome.jpg\" format=\"webp\" widths=\"480 768 1200\" quality=\"80\" loading=\"lazy\" decoding=\"async\" inferSize=\"\" index=\"0\"></p>\n<p>Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.</p>\n<p><img src=\"http://localhost:1337/uploads/we_love_pizza_8452b56f30.jpg\" alt=\"we-love-pizza.jpg\" format=\"webp\" widths=\"480 768 1200\" quality=\"80\" loading=\"lazy\" decoding=\"async\" inferSize=\"\" index=\"1\"></p>\n<p>end of the blog post</p>",
    "metadata": {
      "headings": [],
      "localImagePaths": [],
      // missing the remote URLs mapped at the astro.config.ts
      "remoteImagePaths": [
        /*
          "http://localhost:1337/uploads/this_shrimp_is_awesome_9c30d9f773.jpg",
          "http://localhost:1337/uploads/we_love_pizza_8452b56f30.jpg"
        */
      ],
      "frontmatter": {}
    }
  },
  "collection": "blogs"
}

Note

I checked the code on the v5.17.1 tag and also on the latest branch, and on both, we have the same code missing

What's the expected result?

When processing the remote markdown content, and having the remote images configured at the astro.config, I expect that the content-layer uses it to track and process the remote images that matchs if the configuration

A possible fix

Update the code of content-layer ( createMarkdownProcessor line 143 ) to something like the following

async #processMarkdown(content: string): Promise<RenderedContent> {
  const config = this.#settings.config;
  this.#markdownProcessor ??= await createMarkdownProcessor({
    image: config.image,
    experimentalHeadingIdCompat: config.experimental.headingIdCompat,
    ...config.markdown
  });
  const { code, metadata } = await this.#markdownProcessor.render(content);
  return {
    html: code,
    metadata,
  };
}

Temporary workaround

Link to Minimal Reproducible Example

https://github.com/erkobridee/strapicms-astro-client/tree/a5771991034b9b7fb2759bfb45570d2e37564afc

As described above, this project loads content from the Strapi CMS.

Backend repository: https://github.com/erkobridee/strapicms-server

Participation

  • I am willing to submit a pull request for this issue.

Metadata

Metadata

Assignees

No one assigned

    Labels

    in reviewHas been triaged but not yet decided if it is a bug or not.needs reproIssue needs a reproduction

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions