diff --git a/website/.gitignore b/website/.gitignore
new file mode 100644
index 000000000..ffd492d01
--- /dev/null
+++ b/website/.gitignore
@@ -0,0 +1 @@
+public/sitemap.xml
diff --git a/website/adapters/netlify-edge/vite.config.ts b/website/adapters/netlify-edge/vite.config.ts
index 67fdae2f5..d9e85ef35 100644
--- a/website/adapters/netlify-edge/vite.config.ts
+++ b/website/adapters/netlify-edge/vite.config.ts
@@ -11,6 +11,13 @@ export default extendConfig(baseConfig, () => {
},
outDir: '.netlify/edge-functions/entry.netlify-edge',
},
- plugins: [netlifyEdgeAdapter()],
+ plugins: [
+ netlifyEdgeAdapter({
+ ssg: {
+ include: [],
+ sitemapOutFile: null,
+ },
+ }),
+ ],
};
});
diff --git a/website/netlify.toml b/website/netlify.toml
index d1edf8c94..63cdece29 100644
--- a/website/netlify.toml
+++ b/website/netlify.toml
@@ -1,3 +1,3 @@
[build]
publish = "dist"
-command = "npm run build"
+command = "npm run sitemap && npm run build"
diff --git a/website/package.json b/website/package.json
index 12a9c7990..b393d22d7 100644
--- a/website/package.json
+++ b/website/package.json
@@ -17,6 +17,7 @@
"build.server": "vite build -c adapters/netlify-edge/vite.config.ts",
"build.types": "tsc --incremental --noEmit",
"contributors": "tsm ./scripts/contributors.ts",
+ "sitemap": "tsm ./scripts/sitemap.ts",
"deploy": "netlify deploy --build",
"dev": "vite --mode ssr",
"dev.debug": "node --inspect-brk ./node_modules/vite/bin/vite.js --mode ssr --force",
diff --git a/website/scripts/contributors.ts b/website/scripts/contributors.ts
index c119945da..a15b64dfa 100644
--- a/website/scripts/contributors.ts
+++ b/website/scripts/contributors.ts
@@ -17,11 +17,11 @@ const GITHUB_PERSONAL_ACCESS_TOKEN = process.env.GITHUB_PERSONAL_ACCESS_TOKEN;
const EXCLUDED_COMMITS = ['2cc351f6db7798cf60276225abcbacbc1ea491db'];
/**
- * Finds all index files in the given directory.
+ * Finds all index files in the given directories.
*
* @param directories The directories to search in.
*/
-async function findIndexFiles(directories: string[]) {
+function findIndexFiles(directories: string[]) {
// Create file paths list
const filePaths: string[] = [];
@@ -40,7 +40,7 @@ async function findIndexFiles(directories: string[]) {
const itemPath = path.join(directory, itemName);
const itemStat = fs.statSync(itemPath);
if (itemStat.isDirectory()) {
- filePaths.push(...(await findIndexFiles([itemPath])));
+ filePaths.push(...findIndexFiles([itemPath]));
}
}
}
@@ -60,7 +60,7 @@ async function updateContributors() {
}
// Find all MDX files of guides and API reference
- const filePaths = await findIndexFiles([
+ const filePaths = findIndexFiles([
path.join('src', 'routes', 'guides'),
path.join('src', 'routes', 'api'),
]);
diff --git a/website/scripts/sitemap.ts b/website/scripts/sitemap.ts
new file mode 100644
index 000000000..a10a95b90
--- /dev/null
+++ b/website/scripts/sitemap.ts
@@ -0,0 +1,71 @@
+import fs from 'node:fs';
+import path from 'node:path';
+
+const ORIGIN = 'https://valibot.dev/';
+
+/**
+ * Finds all index files in the given directory.
+ *
+ * @param directory The directory to search in.
+ */
+function findIndexFiles(directory: string) {
+ // Create file paths list
+ const filePaths: string[] = [];
+
+ // Get items of directory
+ const items = fs.readdirSync(directory);
+
+ for (const itemName of items) {
+ // If item is a index file, add it to list
+ if (itemName === 'index.tsx' || itemName === 'index.mdx') {
+ filePaths.push(path.join(directory, itemName));
+
+ // Otherwise, search for nested index files
+ } else {
+ const itemPath = path.join(directory, itemName);
+ const itemStat = fs.statSync(itemPath);
+ if (itemStat.isDirectory()) {
+ filePaths.push(...findIndexFiles(itemPath));
+ }
+ }
+ }
+
+ // Return file paths list
+ return filePaths;
+}
+
+/**
+ * Generates the sitemap of the website.
+ */
+async function generateSitemap() {
+ // Find all route index files
+ const filePaths = findIndexFiles(path.join('src', 'routes'));
+
+ // Create URL paths and sort them
+ const urlSet = filePaths
+ // Transform file paths to URL paths
+ .map((filePath) =>
+ filePath
+ .replace(/\\/g, '/')
+ .replace(/src\/routes\//, '')
+ .replace(/\(.+\)\//, '')
+ .replace(/index\.(tsx|mdx)/, '')
+ )
+ // Sort URL paths alphabetically
+ .sort()
+ // Reduce URL paths to URL set
+ .reduce(
+ (urlPaths, urlPath) =>
+ `${urlPaths}${ORIGIN}${urlPath}`,
+ ''
+ );
+
+ // Write sitemap.xml to public directory
+ fs.writeFileSync(
+ path.join('public', 'sitemap.xml'),
+ `${urlSet}`
+ );
+}
+
+// Start generation of sitemap
+generateSitemap();