I added llms.txt to this site built with Astro, so I’ll introduce the code.
Exploring Astro Plugins
First, I searched for Astro Integrations (plugins) that could easily add llms.txt. At present, none that support llms.txt were found.
AI-Assisted Implementation
Since there was no plugin and it would be faster to create it myself this time, I asked Cursor (claude-3.7-sonnet) Agent mode to implement it.
The overview of specifications I described in the prompt was as follows:
Please implement to return responses in the following format for all pages
- [title](url): descriptionllms.txt Implementation Code
Here’s the code created through Vibe Coding with Cursor.
(Please modify appropriately according to your project structure and specific requirements.)
src/pages/llms.txt.js
/**
* Generate a complete site map with formatted Markdown links
*/
export async function GET(context) {
const baseUrl = "https://codenote.net";
// Get data
const posts = await fetchAllPosts();
const tags = extractAllTags(posts);
// Generate formatted content
const formattedEntries = [
...generateHeader(),
...generateStaticPages(baseUrl),
...generatePostsSection(posts, baseUrl),
...generateTagsSection(tags, baseUrl)
];
// Return response as a text file
return new Response(formattedEntries.join('\n'), {
headers: {
"Content-Type": "text/plain; charset=utf-8",
},
});
}
/**
* Fetch all posts from the posts directory
*/
async function fetchAllPosts() {
const postFiles = await import.meta.glob('./posts/*.md', { eager: true });
return Object.values(postFiles);
}
/**
* Extract all unique tags from posts
*/
function extractAllTags(posts) {
const tagSet = new Set();
posts.forEach(post => {
if (post.frontmatter?.tags && Array.isArray(post.frontmatter.tags)) {
post.frontmatter.tags.forEach(tag => tagSet.add(tag));
}
});
return Array.from(tagSet);
}
/**
* Generate the document header
*/
function generateHeader() {
return [
`# CodeNote.net`,
``,
];
}
/**
* Generate links for static pages
*/
function generateStaticPages(baseUrl) {
return [
`- [Home](${baseUrl}/): Top page of CodeNote`,
``,
`## Second directories`,
``,
`- [About](${baseUrl}/about): About page and profile information`,
`- [Posts](${baseUrl}/posts): All blog posts`,
`- [Tags](${baseUrl}/tags): All available tags`,
`- [RSS Feed](${baseUrl}/rss.xml): Subscribe to the blog updates`,
];
}
/**
* Generate the posts section with links to all posts
*/
function generatePostsSection(posts, baseUrl) {
const result = [
``,
`## Posts`,
``
];
posts.forEach(post => {
const url = getPostUrl(post, baseUrl);
if (url) {
const title = post.frontmatter?.title || "Untitled";
const description = post.frontmatter?.description || "";
result.push(`- [${title}](${url}): ${description}`);
}
});
return result;
}
/**
* Get the URL for a post
*/
function getPostUrl(post, baseUrl) {
if (post.url) {
return `${baseUrl}${post.url}`;
} else if (post.file) {
const filename = post.file.split('/').pop()?.replace(/\.md$/, '');
if (filename) {
return `${baseUrl}/posts/${filename}`;
}
}
return null;
}
/**
* Generate the tags section with links to all tag pages
*/
function generateTagsSection(tags, baseUrl) {
const result = [
``,
`## Tags`,
``
];
tags.forEach(tag => {
result.push(`- [#${tag}](${baseUrl}/tags/${tag}): Posts tagged with #${tag}`);
});
return result;
}
export const prerender = true;That’s all from the Gemba.