From 5f114e21e7943284bcf77e770a980186d8595dd2 Mon Sep 17 00:00:00 2001 From: Gabriel Franco Date: Tue, 29 Sep 2026 12:12:07 -0300 Subject: [PATCH] sitemap and rss --- astro.config.mjs | 3 +- package-lock.json | 192 ++++++++++++++++++ package.json | 2 + public/robots.txt | 4 + src/content.config.ts | 1 + src/content/posts/en/hello-world.mdx | 1 + src/content/posts/en/spotify-complaining.mdx | 1 + ...lugin4shell-git-trick-ai-coding-agents.mdx | 1 + src/content/posts/pt/hello-world.mdx | 1 + src/content/posts/pt/spotify-complaining.mdx | 1 + ...lugin4shell-git-trick-ai-coding-agents.mdx | 1 + src/layouts/BaseLayout.astro | 1 + src/pages/feed.xml.ts | 19 ++ 13 files changed, 227 insertions(+), 1 deletion(-) create mode 100644 public/robots.txt create mode 100644 src/pages/feed.xml.ts diff --git a/astro.config.mjs b/astro.config.mjs index 3d05b0d..a39ffd9 100644 --- a/astro.config.mjs +++ b/astro.config.mjs @@ -3,6 +3,7 @@ import { defineConfig } from 'astro/config'; import react from '@astrojs/react'; import mdx from '@astrojs/mdx'; +import sitemap from '@astrojs/sitemap' import tailwindcss from '@tailwindcss/vite'; import vercel from '@astrojs/vercel'; @@ -18,7 +19,7 @@ export default defineConfig({ }, }, - integrations: [react(), mdx()], + integrations: [react(), mdx(), sitemap()], adapter: vercel({ webAnalytics: { enabled: true }, diff --git a/package-lock.json b/package-lock.json index afbadb1..6645ba3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,6 +11,8 @@ "@astrojs/markdown-satteri": "^0.4.0", "@astrojs/mdx": "^8.0.0", "@astrojs/react": "^6.0.5", + "@astrojs/rss": "^4.0.19", + "@astrojs/sitemap": "^3.7.4", "@astrojs/vercel": "^11.0.9", "@tailwindcss/vite": "^4.3.3", "@types/react": "^19.2.18", @@ -289,6 +291,27 @@ "react-dom": "^17.0.2 || ^18.0.0 || ^19.0.0" } }, + "node_modules/@astrojs/rss": { + "version": "4.0.19", + "resolved": "https://registry.npmjs.org/@astrojs/rss/-/rss-4.0.19.tgz", + "integrity": "sha512-e+z5wYeYtffQdHQO8c2tkSd2JEBdAuRXJV4ZEU5IxkYeE6e39woDd7nw1PH1Kk2tEYNCYuKdylnnbhGmt61awA==", + "license": "MIT", + "dependencies": { + "fast-xml-parser": "^5.5.7", + "piccolore": "^0.1.3", + "zod": "^4.3.6" + } + }, + "node_modules/@astrojs/sitemap": { + "version": "3.7.4", + "resolved": "https://registry.npmjs.org/@astrojs/sitemap/-/sitemap-3.7.4.tgz", + "integrity": "sha512-LbKNC24bdUWcQf/pThB6qLlSqHojxGjZDURIzFocY8rlWnAn2t74nnhnK6S5x0NHriHoAduLEpVjRykmeGiVvA==", + "license": "MIT", + "dependencies": { + "sitemap": "^9.0.0", + "zod": "^4.3.6" + } + }, "node_modules/@astrojs/telemetry": { "version": "3.3.3", "resolved": "https://registry.npmjs.org/@astrojs/telemetry/-/telemetry-3.3.3.tgz", @@ -1894,6 +1917,18 @@ "@emnapi/runtime": "^1.7.1 || ^2.0.0-alpha.4" } }, + "node_modules/@nodable/entities": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@nodable/entities/-/entities-3.1.0.tgz", + "integrity": "sha512-LsS/DjHr+uDM647Gru/cA8+J3a3HfhttwCKLyuoyN7yXTFCxKBtSgMQBvrW9yNPa2/zDRUNuGPaH5QUFoa4arQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/nodable" + } + ], + "license": "MIT" + }, "node_modules/@oslojs/encoding": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@oslojs/encoding/-/encoding-1.1.0.tgz", @@ -2898,6 +2933,15 @@ "@types/unist": "*" } }, + "node_modules/@types/node": { + "version": "24.19.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-24.19.0.tgz", + "integrity": "sha512-zY+5tKxXdhGh1PYI0ac+7juvEu4OI6vWtVVoj5i2m42jxAY1U+zHGt6QCyOFwykdP62sM3MJ9stoYYUw5aCWew==", + "license": "MIT", + "dependencies": { + "undici-types": ">=7.24.0 <7.24.7" + } + }, "node_modules/@types/react": { "version": "19.2.18", "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.18.tgz", @@ -2916,6 +2960,15 @@ "@types/react": "^19.2.0" } }, + "node_modules/@types/sax": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/@types/sax/-/sax-1.2.7.tgz", + "integrity": "sha512-rO73L89PJxeYM3s3pPPjiPgVVcymqU490g0YO5n5By0k2Erzj6tay/4lr1CHAAU4JyOWd1rpQ8bCf6cZfHU96A==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/unist": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz", @@ -3155,6 +3208,24 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/anynum": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/anynum/-/anynum-1.0.1.tgz", + "integrity": "sha512-N6//FLET/tXYNM/F6ABca1oH6fWB+KlTt909Le28WMDBk8oaT4vY17DCrwg2MvmuqUKt3Ni4N5dGJ/EoBgcO6A==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "license": "MIT" + }, + "node_modules/arg": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", + "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==", + "license": "MIT" + }, "node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", @@ -3941,6 +4012,45 @@ "fast-string-width": "^3.0.2" } }, + "node_modules/fast-xml-builder": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/fast-xml-builder/-/fast-xml-builder-1.3.1.tgz", + "integrity": "sha512-pIM/1n3ntFXKYrUZwW7QCK0gAW7XY+wzj1YMIV3tLDvPj/V+zTGJK5e3/4WJfwj0qWw2ElNXiTixda/R+3YSug==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "license": "MIT", + "dependencies": { + "path-expression-matcher": "^1.6.2", + "xml-naming": "^0.3.0" + } + }, + "node_modules/fast-xml-parser": { + "version": "5.11.2", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-5.11.2.tgz", + "integrity": "sha512-R9iDuNrQYeQut46cn2r2wHKn4HYzVDvDm5J1wW+koZewykv0yuO2HChTYeZtrULyHIDM9cj9TUXloCsueCQUog==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "license": "MIT", + "dependencies": { + "@nodable/entities": "^3.0.1", + "fast-xml-builder": "^1.2.0", + "is-unsafe": "^2.0.0", + "path-expression-matcher": "^1.6.2", + "strnum": "^2.4.2", + "xml-naming": "^0.3.0" + }, + "bin": { + "fxparser": "src/cli/cli.js" + } + }, "node_modules/fdir": { "version": "6.5.0", "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", @@ -4227,6 +4337,18 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/is-unsafe": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-unsafe/-/is-unsafe-2.0.2.tgz", + "integrity": "sha512-HgbIHPBH0KHHCcjLfGsCvhtPTVxjaAZlXjwdz7/GQC40SjSe4sfQsar8J5VFo8JOSbarkpV0OLG95bbaNd9aAQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "license": "MIT" + }, "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", @@ -5036,6 +5158,21 @@ "integrity": "sha512-yQA4H19AmPEoMUeavPMDIe1higySl/gH/yaQrkT/s07Qp+7pp2hYz30N3z2l5BkjVkF9Ow6o0wjJamm2y7Sn0A==", "license": "MIT" }, + "node_modules/path-expression-matcher": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/path-expression-matcher/-/path-expression-matcher-1.6.2.tgz", + "integrity": "sha512-enSlaiat05iasnzmgNxRj8reFdj3puY2QpNgP1aPIaVfT6nn9ICuPoFlKHk8EN22HcwewshO+mN2DGbkCEOtqQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, "node_modules/path-key": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", @@ -5469,6 +5606,25 @@ "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", "license": "MIT" }, + "node_modules/sitemap": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/sitemap/-/sitemap-9.0.1.tgz", + "integrity": "sha512-S6hzjGJSG3d6if0YoF5kTyeRJvia6FSTBroE5fQ0bu1QNxyJqhhinfUsXi9fH3MgtXODWvwo2BDyQSnhPQ88uQ==", + "license": "MIT", + "dependencies": { + "@types/node": "^24.9.2", + "@types/sax": "^1.2.1", + "arg": "^5.0.0", + "sax": "^1.4.1" + }, + "bin": { + "sitemap": "dist/esm/cli.js" + }, + "engines": { + "node": ">=20.19.5", + "npm": ">=10.8.2" + } + }, "node_modules/smol-toml": { "version": "1.8.0", "resolved": "https://registry.npmjs.org/smol-toml/-/smol-toml-1.8.0.tgz", @@ -5523,6 +5679,21 @@ "node": ">=6" } }, + "node_modules/strnum": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/strnum/-/strnum-2.4.2.tgz", + "integrity": "sha512-rDG3Ah4TV0k1hWvLSzkZtMmLN9+eS+h3knq4MP6A42Y3Yh5qGNnOUs1jJkoSr8FG5dsL28c7KgkIBzSEykqtuw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "license": "MIT", + "dependencies": { + "anynum": "^1.0.1" + } + }, "node_modules/svgo": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/svgo/-/svgo-4.1.0.tgz", @@ -5692,6 +5863,12 @@ "node": ">=22.19.0" } }, + "node_modules/undici-types": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.24.6.tgz", + "integrity": "sha512-WRNW+sJgj5OBN4/0JpHFqtqzhpbnV0GuB+OozA9gCL7a993SmU+1JBZCzLNxYsbMfIeDL+lTsphD5jN5N+n0zg==", + "license": "MIT" + }, "node_modules/unified": { "version": "11.0.5", "resolved": "https://registry.npmjs.org/unified/-/unified-11.0.5.tgz", @@ -6113,6 +6290,21 @@ "node": ">= 6.0" } }, + "node_modules/xml-naming": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/xml-naming/-/xml-naming-0.3.0.tgz", + "integrity": "sha512-ghig2TBE/H11aOVgmahA3MhimvkBr6JIYknH/Dhdk10nXwdbIqBJsbfMxpvFPG8bAw77gN29aQWvKpmVoPlvPQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "license": "MIT", + "engines": { + "node": ">=16.0.0" + } + }, "node_modules/xxhash-wasm": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/xxhash-wasm/-/xxhash-wasm-1.1.0.tgz", diff --git a/package.json b/package.json index b9497d8..2b6de43 100644 --- a/package.json +++ b/package.json @@ -16,6 +16,8 @@ "@astrojs/markdown-satteri": "^0.4.0", "@astrojs/mdx": "^8.0.0", "@astrojs/react": "^6.0.5", + "@astrojs/rss": "^4.0.19", + "@astrojs/sitemap": "^3.7.4", "@astrojs/vercel": "^11.0.9", "@tailwindcss/vite": "^4.3.3", "@types/react": "^19.2.18", diff --git a/public/robots.txt b/public/robots.txt new file mode 100644 index 0000000..e594c2c --- /dev/null +++ b/public/robots.txt @@ -0,0 +1,4 @@ +User-agent: * +Allow: / + +Sitemap: https://gabeefran.co/sitemap-index.xml diff --git a/src/content.config.ts b/src/content.config.ts index a2bf7d9..08b3ad3 100644 --- a/src/content.config.ts +++ b/src/content.config.ts @@ -10,6 +10,7 @@ const posts = defineCollection({ title: z.string(), description: z.string(), pubDate: z.coerce.date(), + slug: z.string(), updatedDate: z.coerce.date().optional(), tags: z.array(z.string()).default([]), draft: z.boolean().default(false), diff --git a/src/content/posts/en/hello-world.mdx b/src/content/posts/en/hello-world.mdx index ba358c5..dac9858 100644 --- a/src/content/posts/en/hello-world.mdx +++ b/src/content/posts/en/hello-world.mdx @@ -1,5 +1,6 @@ --- title: "This blog's Hello World (or whatever you want to call this site)" +slug: "hello-world" description: "A short note on why this exists and what I plan to write about here." pubDate: 2026-09-22 tags: ["meta", "blogging"] diff --git a/src/content/posts/en/spotify-complaining.mdx b/src/content/posts/en/spotify-complaining.mdx index 48cdb1b..e3f905d 100644 --- a/src/content/posts/en/spotify-complaining.mdx +++ b/src/content/posts/en/spotify-complaining.mdx @@ -1,5 +1,6 @@ --- title: "Spotify's Time Capsule Change and the Enshittification of Software" +slug: "spotify-complaining" description: "Spotify just removed one of its best features. Beyond a bit of complaining, I want to open a debate about what software is turning into." pubDate: 2026-09-2 tags: ["software", "life"] diff --git a/src/content/posts/en/understanding-plugin4shell-git-trick-ai-coding-agents.mdx b/src/content/posts/en/understanding-plugin4shell-git-trick-ai-coding-agents.mdx index bcd7352..31cdc24 100644 --- a/src/content/posts/en/understanding-plugin4shell-git-trick-ai-coding-agents.mdx +++ b/src/content/posts/en/understanding-plugin4shell-git-trick-ai-coding-agents.mdx @@ -1,6 +1,7 @@ --- title: "Understanding Plugin4Shell: An Exploit That Uses a Simple Git Trick to Fool AI Coding Agents" description: "A git branch named after a commit hash was enough to make AI coding agents run unverified plugins. I reproduced the Plugin4Shell trick on GitHub and Forgejo." +slug: "understanding-plugin4shell-git-trick-ai-coding-agents" pubDate: 2026-09-28 tags: ["cybersecurity", "git", "ai", "software"] seoKeywords: "Plugin4Shell, git branch named after commit hash, SHA pinning bypass, AI coding agents security, Claude Code plugin vulnerability, supply chain attack, git internals, Forgejo" diff --git a/src/content/posts/pt/hello-world.mdx b/src/content/posts/pt/hello-world.mdx index 18564df..86a4659 100644 --- a/src/content/posts/pt/hello-world.mdx +++ b/src/content/posts/pt/hello-world.mdx @@ -2,6 +2,7 @@ title: "O Hello World desse blog (ou seja lá como você queira chamar esse site)" description: "Uma nota curta sobre por que isso existe e sobre o que pretendo escrever aqui." pubDate: 2026-09-22 +slug: "hello-world" tags: ["meta", "blogging"] --- diff --git a/src/content/posts/pt/spotify-complaining.mdx b/src/content/posts/pt/spotify-complaining.mdx index 53f4164..1b9d14f 100644 --- a/src/content/posts/pt/spotify-complaining.mdx +++ b/src/content/posts/pt/spotify-complaining.mdx @@ -1,6 +1,7 @@ --- title: "A mudança na cápsula do tempo do Spotify e a bostificação do software" description: "Spotify simplesmente removeu uma das suas melhores funcionalidades. Além de reclamar um pouco, quero abrir um debate sobre o que os softwares estão se tornando." +slug: "spotify-complaining" pubDate: 2026-09-2 tags: ["software", "life"] --- diff --git a/src/content/posts/pt/understanding-plugin4shell-git-trick-ai-coding-agents.mdx b/src/content/posts/pt/understanding-plugin4shell-git-trick-ai-coding-agents.mdx index 773041a..a57ca08 100644 --- a/src/content/posts/pt/understanding-plugin4shell-git-trick-ai-coding-agents.mdx +++ b/src/content/posts/pt/understanding-plugin4shell-git-trick-ai-coding-agents.mdx @@ -1,6 +1,7 @@ --- title: "Entendendo o Plugin4Shell: um exploit que usa um truque simples do git para enganar agentes de IA de programação" description: "Uma branch do git com o nome de um hash de commit bastou para fazer agentes de IA de programação rodarem plugins não verificados. Reproduzi o truque do Plugin4Shell no GitHub e no Forgejo." +slug: "understanding-plugin4shell-git-trick-ai-coding-agents" pubDate: 2026-09-28 tags: ["cybersecurity", "git", "ai", "software"] seoKeywords: "Plugin4Shell, branch do git com nome de hash de commit, bypass de SHA pinning, segurança de agentes de IA de programação, vulnerabilidade de plugin do Claude Code, ataque à cadeia de suprimentos, internals do git, Forgejo" diff --git a/src/layouts/BaseLayout.astro b/src/layouts/BaseLayout.astro index c314797..1c2d8fd 100644 --- a/src/layouts/BaseLayout.astro +++ b/src/layouts/BaseLayout.astro @@ -34,6 +34,7 @@ const canonicalURL = new URL(Astro.url.pathname, Astro.site); + {title} diff --git a/src/pages/feed.xml.ts b/src/pages/feed.xml.ts new file mode 100644 index 0000000..37a2133 --- /dev/null +++ b/src/pages/feed.xml.ts @@ -0,0 +1,19 @@ +import rss from '@astrojs/rss'; +import { getCollection } from 'astro:content'; + +export async function GET(context) { + const blog = await getCollection('posts'); + return rss({ + title: 'gabeefran.co', + description: 'Gabriel Franco\'s notes about computer science and other topics', + site: context.site, + items: blog.map((post) => ({ + title: post.data.title, + pubDate: post.data.pubDate, + description: post.data.description, + // Compute RSS link from post `slug` + // This example assumes all posts are rendered as `/blog/[slug]` routes + link: `/posts/${post.data.slug}/`, + })), + }); +}