Generating dynamic sitemaps with Qwik City & Builder.io
A clever way of generating dynamic site maps in a Qwik City app with updated data from the builder.io content API is to use middleware. You can construct the site map using the data and send a response to the client as XML.
Create a new route called sitemap.
This will dynamically generate a sitemap of all your builder pages at 'https://base-url/sitemap'.
import { type RequestHandler } from "@builder.io/qwik-city";
export const onGet: RequestHandler = async (req) => {
const data = await fetch(
"https://cdn.builder.io/api/v2/content/page?apiKey=your-api-key&fields=data.url&query.data.includeInSitemap.$ne=false"
);
if (!data.ok) {
throw req.error(404, "Error fetching content");
}
const res = await data.json();
const pageUrls = res.results.map((page: any) => page.data.url);
console.log(pageUrls);
let sitemapXml =
'<?xml version="1.0" encoding="UTF-8"?>\n<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">\n';
pageUrls.forEach((url: string) => {
sitemapXml += `<url><loc>https://YOUR-BASE-URL${url}</loc></url>\n`;
});
sitemapXml += "</urlset>";
const response = new Response(sitemapXml, {
status: 200,
headers: {
"Content-Type": "text/xml",
},
});
console.log(response);
req.send(response);
};
You could also create a dynamic route like 'sitemap/[slug]/index.tsx' to dynamically generate more than one site map.
import { type RequestHandler } from "@builder.io/qwik-city";
import { getContent } from "@builder.io/sdk-qwik";
const API_KEY = import.meta.env.PUBLIC_BUILDER_API_KEY;
export const onGet: RequestHandler = async (req) => {
const slug = req.params.slug;
console.log(slug);
const entry = await getContent({
model: "blog-article",
apiKey: API_KEY,
query: { "data.handle": slug },
options: { includeRefs: true },
});
console.log(entry);
let sitemapXml =
'<?xml version="1.0" encoding="UTF-8"?>\n<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">\n';
sitemapXml += `
<url>
<loc>https://YOUR-BASE_URL/blog/${slug}</loc>
<lastmod>${new Date(entry?.data?.date).toISOString()}</lastmod>
<changefreq>monthly</changefreq>
<priority>0.8</priority>
</url>\n`;
sitemapXml += "</urlset>";
const response = new Response(sitemapXml, {
status: 200,
headers: {
"Content-Type": "text/xml",
},
});
console.log(response);
req.send(response);
};