
Dynamic XML Sitemap with Spring Boot and Contentful Instead of Angular
Discover why I generate my XML sitemap with Spring Boot instead of Angular. New Contentful articles automatically appear in the sitemap without rebuilding or redeploying the frontend, making the architecture cleaner, more scalable, and easier to maintain.
π‘ The Starting Point
When I started building my project, the sitemap.xml was generated by the Angular frontend.For a small website, this approach works perfectly fine. However, as the number of articles grew, one major drawback became obvious. Every new article required:
π¨ a new Angular build
π³ a new Docker image
π a frontend deployment
π only then could Google discover the new article through the updated sitemap
Even though nothing in the frontend had actually changed.That was the moment I started questioning the architecture.
β Who Should Own the Sitemap?
A sitemap only describes the content of a website. But the content itself does not come from Angular. It is managed entirely in Contentful and already processed by the Spring Boot backend. So I asked myself one simple question:
Why should the frontend generate the sitemap when the backend already owns all the data?
ποΈ The Original Architecture
The original content flow looked like this:
Contentful β Spring Boot API β Angular SSR
Angular SSR was then responsible for two separate outputs:
π Rendering the HTML pages
πΊοΈ Providing the static
sitemap.xml
This meant the frontend was responsible for both rendering the application and generating SEO-related files.
The result was an unnecessary dependency between content publishing and frontend deployment.
π The New Architecture
I moved the entire sitemap generation into the Spring Boot backend.
The backend already knows everything required to build a valid XML sitemap:
π Every published article
π Every available language version
π Publication and last update dates
π Every public URL
Because of that, the backend can generate the sitemap dynamically without any help from the frontend.
The new architecture is much simpler:
Contentful β¬οΈ Spring Boot
Spring Boot now provides two independent outputs:
π REST API
πΊοΈ Dynamic
sitemap.xml
The sitemap is delivered directly to search engines through Traefik, while Angular SSR is responsible only for rendering the user interface.
The frontend no longer has any SEO-related responsibility. Publishing a new article automatically updates the sitemap without rebuilding or redeploying Angular.
βοΈ The Entry Point
The entire XML sitemap is exposed through a dedicated REST endpoint. The controller itself contains no business logic. Its only responsibility is to delegate the request to the service layer.
@RestController
public class SitemapController {
private final SitemapService sitemapService;
public SitemapController(SitemapService sitemapService) {
this.sitemapService = sitemapService;
}
@GetMapping(
value = "/sitemap.xml",
produces = "application/xml"
)
public ResponseEntity<String> getSitemap() {
return ResponseEntity.ok(
sitemapService.generateSitemap()
);
}
}βοΈ How It Works Today
The entire publishing process is now fully automated.
βοΈ Publish an article in Contentful
π Spring Boot retrieves the new content
πΊοΈ The XML sitemap is updated automatically
π€ Google discovers the new URL during its next sitemap crawl
There is:
β no Angular build
β no frontend Docker image
β no frontend deployment
Only the content changes.The infrastructure remains untouched.
π What the Sitemap Contains
The generated sitemap automatically includes:
β all static pages
β all blog articles
β
lastmodβ
hreflanglinks for English and German
β SEO-friendly URLs
The sitemap always reflects the current state of the website.
<url>
<loc>
https://redneckworks.bielski.nrw/en/blog/dynamic-xml-sitemap
</loc>
<lastmod>2026-07-23</lastmod>
<xhtml:link
rel="alternate"
hreflang="de"
href="https://redneckworks.bielski.nrw/de/blog/dynamic-xml-sitemap"/>
<xhtml:link
rel="alternate"
hreflang="en"
href="https://redneckworks.bielski.nrw/en/blog/dynamic-xml-sitemap"/>
</url>π§ An Interesting Challenge
During the migration I ran into an unexpected issue.
After removing the static sitemap.xmlfrom Angular SSR,
requests were initially redirected to/sitemap.xml/home
The fix was to configure Traefik so that every request for/sitemap.xmlis routed directly to the Spring Boot backend instead of the frontend.
Today https://redneckworks.bielski.nrw/sitemap.xml is served directly by the backend.
curl https://redneckworks.bielski.nrw/sitemap.xmlHTTP/2 200 OK
Content-Type: application/xml;charset=UTF-8
Cache-Control: public, max-age=86400
It really works.
π Google Search Console
After deploying the new implementation, I simply resubmitted the existing sitemap in Google Search Console. From now on, every newly published article will automatically appear in the sitemap and can be discovered by Google during future crawls.No additional deployment is required.
β Benefits of the New Architecture
ποΈ Clear separation of responsibilities
π No frontend deployment for new content
β‘ Always up-to-date XML sitemap
π€ Better SEO automation
π³ Fewer Docker builds
π Much simpler publishing workflow
π¬ Related Video
Dynamic XML Sitemap with Spring Boot & Contentful
In this video, I explain why I moved XML sitemap generation from the Angular frontend into the Spring Boot backend.
You'll see:
the original architecture
why Angular was the wrong place for the sitemap
the complete Spring Boot implementation
deployment without rebuilding the frontend
verification in Google Search Console
how every new Contentful article is automatically added to the XML sitemap
Instead of discussing only the theory, I demonstrate the complete implementation, explain the architectural decisions behind it, and show the entire deployment process step by step.
π― Final Thoughts
This was a relatively small technical change, but it significantly improved the overall architecture.Responsibilities are now clearly separated.
Component | Responsibility |
π Contentful | Content Management |
β Spring Boot | Business Logic, REST API & XML Sitemap |
π °οΈ Angular SSR | User Interface Rendering |
π Google | Crawl the Sitemap & Index Content |
For me, this is a great example of how software architecture evolves over time. At the beginning of a project, many solutions seem perfectly reasonable. As the project grows, you start to recognize which component should actually own a specific responsibility.
In my case, the conclusion became obvious:
